0

I have C static library that has a struct global variable defined within it. I wish to access that variable within C++ code that will link to that C library. At the moment, I am getting "ld: symbol(s) not found for architecture x86_64" errors.

I am trying the following (simplified struct for the sake of the question):

// library.h
#ifdef __cplusplus
  extern "C" {
#endif

typedef struct {
  int simpleVariableA;
  int simpleVariableB;
} GlobalStruct;

extern GlobalStruct gs;
#ifdef __cplusplus
  }
#endif

// library.c
#include "library.h"
GlobalStruct gs;

Library.c and library.h are compiled into library.a, a statically-linked library. I then want to link a C++ file to the library, but get errors.

// main.cpp
#include "library.h"

int main(int argc, char** argv) {
  gs.simpleVariableA = 1;
  gs.simpleVariableB = 1;
}

What am I doing wrong? I have run "nm -g library.a" and get "0000000000000008 C _gs" back, so I think this means that the symbol is being exported, no? Is it an issue with C++ not finding C code?

I compile the files like this:

gcc -c library.c -o library.o
ar rcs liblibrary.a library.o
g++ main.cpp -L. -llibrary

BTW, I get an error with the ar command:

warning: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: warning for library: liblibrary.a the table of contents is empty (no object file members in the library define global symbols)

However, this error goes away if I define a function f() in library.h and library.c and compile this into the library.

John
  • 10,837
  • 17
  • 78
  • 141

1 Answers1

3

Each of your mentions of gs is merely a declaration (that is it indicates that there is a thing by this name somewhere), but none of them is a definition (which is something which additionally sets aside space for the named thing).

If you initialise gs in library.c, your problem goes away:

GlobalStruct gs = { 0, 0 };

The function of the extern keyword in your library.h is specifically to stop this being a (tentative) definition. It's possibly redundant in this case, but probably best to include it, and so make sure that there's only one definition of gs, in library.c.

Including the initialiser in library.c also stops the warning message, because that initialiser is what creates the thing that goes in the library (that is, you were correct: the warning was significant for your problem).

Norman Gray
  • 11,978
  • 2
  • 33
  • 56
  • Perfect, thanks very much. I didn't realise that not setting a variable to an initial value means it's not actually properly defined, I had thought mentioning it in the .c file meant it was fully defined. – John Jun 13 '14 at 20:43
  • There's further information about declarations and definitions in [this popular question](http://stackoverflow.com/questions/1410563/) – Norman Gray Jun 16 '14 at 14:44
  • Very nice, thanks very much. My confusion over the definition is based on the fact that a program will compile if you put "Globalstruct gs;" in the .cpp file, so I have always assumed that that was a sufficient definition. – John Jun 17 '14 at 17:40