У меня есть статическая библиотека C, в которой определена глобальная переменная структуры. Я хочу получить доступ к этой переменной в коде C++, который будет ссылаться на эту библиотеку C. На данный момент я получаю "ld: символы (символы), которые не найдены для архитектуры x86_64".
Я пытаюсь сделать следующее (упрощенная структура для вопроса):
// 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 и library.h скомпилированы в library.a, статически связанную библиотеку. Затем я хочу связать файл C++ с библиотекой, но получить ошибки.
// main.cpp
#include "library.h"
int main(int argc, char** argv) {
gs.simpleVariableA = 1;
gs.simpleVariableB = 1;
}
Что я делаю не так? Я запустил "nm -g library.a" и получил "0000000000000008 C _gs", поэтому я думаю, что это означает, что символ экспортируется, нет? Это проблема с C++, не находя C-код?
Я компилирую файлы следующим образом:
gcc -c library.c -o library.o
ar rcs liblibrary.a library.o
g++ main.cpp -L. -llibrary
BTW, я получаю сообщение об ошибке с командой ar:
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)
Однако эта ошибка исчезает, если я определяю функцию f() в библиотеке.h и library.c и компилирую ее в библиотеку.
Каждое из ваших упоминаний о gs
- это просто объявление (то есть оно указывает на то, что есть что-то под этим именем где-то), но ни одно из них не является определением (которое является чем-то, что дополнительно выделяет пространство для названной вещи).
Если вы инициализируете gs
в library.c
, ваша проблема исчезнет:
GlobalStruct gs = { 0, 0 };
Функция ключевого слова extern
в вашей library.h
заключается в том, чтобы остановить это определение (предварительное). В этом случае он может быть избыточным, но, вероятно, лучше всего включить его, поэтому убедитесь, что в library.c
есть только одно определение gs
.
Включение инициализатора в library.c
также останавливает предупреждающее сообщение, потому что этот инициализатор создает то, что входит в библиотеку (то есть вы были правы: предупреждение было значительным для вашей проблемы).