c ++ неопределенные ссылки со статической библиотекой - PullRequest
45 голосов
/ 12 апреля 2010

Я пытаюсь сделать статическую библиотеку из класса, но при попытке ее использовать я всегда получаю ошибки с неопределенными ссылками на что-либо. Я продолжал создавать объектный файл, такой как

g++ -c myClass.cpp -o myClass.o

и затем упаковываем его в

ar rcs myClass.lib myClass.o

Есть кое-что, что я, очевидно, вообще скучаю по этому. Бьюсь об заклад, это что-то с символами. Спасибо за любой совет, я знаю, что это, скорее всего, что-то, что я мог бы узнать, прочитав какой-нибудь учебник, так что извините, если беспокоюсь о глупых вещах снова:)

редактирование:

myClass.h:

class myClass{
    public:
        myClass();
        void function();
};

myClass.cpp:

#include "myClass.h"

myClass::myClass(){}
void myClass::function(){}

программа, использующая класс:

#include "myClass.h"

int main(){
myClass mc;
mc.function();

return 0;
}

наконец-то я скомпилировал это так:

g++ -o main.exe -L. -l myClass main.cpp

ошибка просто классическая:

C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x31): undefined
 reference to `myClass::myClass()'
C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x3c): undefined
 reference to `myClass::function()'
collect2: ld returned 1 exit status

Ответы [ 5 ]

106 голосов
/ 12 апреля 2010

Это , вероятно, проблема порядка ссылок. Когда компоновщик GNU видит библиотеку, он отбрасывает все символы, которые ему не нужны. В этом случае ваша библиотека появляется перед вашим .cpp файлом, поэтому библиотека отбрасывается перед компиляцией .cpp файла. Сделайте это:

g++ -o main.exe main.cpp -L. -lmylib

или

g++ -o main.exe main.cpp myClass.lib

Компоновщик Microsoft не учитывает порядок библиотек в командной строке.

20 голосов
/ 05 июля 2013

Другая возможная причина: забывание extern "C".

Я столкнулся с этим, потому что я пытался связать программу C ++ со статической библиотекой C. В заголовке библиотеки не было extern "C", поэтому компоновщик искал искаженное имя функции, а библиотека фактически имела имя незащищенной функции.

Потребовалось некоторое время, чтобы понять, что происходит, поэтому я надеюсь, что это поможет кому-то еще.

5 голосов
/ 24 августа 2017

Это проблема, связанная с тем, как компоновщик оптимизирует выходной код. Предположим, у нас есть исполняемый файл, который использует две библиотеки: Lib_A и Lib_B . Lib_A зависит от Lib_B Lib_A определяет символы: Lib_A1 и Lib_A2 , а Lib_B определяет символы Lib_B1 и Lib_B2 . Теперь давайте предположим, что исполняемый файл использует только символ Lib_A1 , а Lib_A1 использует символ Lib_B1 , который определен в Lib_B . Символ Lib_B1 никогда не используется в исполняемом файле.

  1. В случае окон компоновщик работает следующим образом: у меня есть исполняемый файл с двумя, который использует несколько библиотек и все символы, используемые в исполняемом файле, и все библиотеки lib_A1 и lib_B1 . Таким образом, мне понадобятся эти два символа, а остальные не нужны. Я буду определять lib_A2 и lib_B2
  2. В случае Linux, если вы связываете Lib_B до Lib_A , например: g++ .... -lLib_B -lLib_A Компоновщик работает следующим образом: у меня есть исполняемый файл, который сначала ссылается Lib_B . Я не вижу, чтобы исполняемый файл использовал символ Lib_B1 или Lib_B2 . Они не нужны, поэтому я буду определять их. Позже увидим компоновщик. О, у меня есть другая библиотека Lib_A . Я вижу, что исполняемый файл использует символ Lib_B1 . Я сохраню его и отменим неиспользованный символ Lib_B2 . Он не видит, что Lib_B1 использует Lib_A1 , который уже не определен.
  3. В случае Linux, если вы связываете Lib_A до Lib_B , например: g++ ... -lLib_A -lLib_B Компоновщик работает следующим образом: у меня есть исполняемый файл, который сначала связывает Lib_A . О, я вижу, что исполняемый файл использует Lib_A1 . Я сохраню их и не определю Lib_A2 . Позже это можно увидеть. О, у меня есть другая библиотека Lib_B . Я вижу, что теперь исполняемый файл с уже связанными символами, использует Lib_B1 , я буду держать их. В результате он сохраняет Lib_B1 и Lib_A1 , а также неопределенный Lib_B2 и Lib_A2 .
5 голосов
/ 12 апреля 2010

Использование:

g++ -o main.exe main.cpp myClass.lib 

Использование пути к библиотеке и флага -l чревато проблемами, но если вы должны это сделать, переименуйте вашу библиотеку в libmylib.a, а затем скомпилируйте как:

g++ -o main.exe main.cpp -L. -lmylib 

Обратите внимание также, что по причинам переносимости, как правило, плохая идея использовать смешанный регистр в именах исходных или выходных файлов.

1 голос
/ 20 марта 2012

Это должно избежать ошибок компоновки и создать общую библиотеку .so:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
...