Неопределенная ссылка на ошибки членов класса библиотеки из вызывающей программы - PullRequest
3 голосов
/ 05 апреля 2011

Дополнительные вопросы добавлены ниже, 4/11/2011

Я занимаюсь разработкой кроссплатформенного набора общих библиотек DLL / SOS и программ для тестирования на C ++, хотя я должен уметьдля поддержки C. Библиотеки будут поставляться только в виде объектного кода, но программы-тестеры будут поставляться с исходным кодом, чтобы наши клиенты могли иметь пример кода.По этой причине я разрабатываю библиотеки для загрузки во время выполнения, т.е. динамическое связывание с использованием dlopen () / LoadLibraryA ().

Я использую g ++ 4.4.3-4 на Umbutu 10.04 и VC ++ 2008 на Vista /64 (в 32-битном режиме).

В Windows все работает нормально (прямо сейчас).Однако, когда я компилирую в Linux, я получаю некоторые ошибки, которые я не могу понять.

Тестер и библиотека имеют несколько классов, закодированных в нескольких .cpp и .h.Классы и большинство всего в библиотеке, кроме основных точек входа, находятся в пространстве имен DISCOVER_NS.

Вот краткий набросок проекта:

Во-первых, признание, я сократилнабор имен, чтобы код был более читабельным.

Discover.cpp

  • Создает объект класса с указателем на него, называемый theMainObject типаDiscoverObject.

  • Имеет внешнюю функцию "C", которая возвращает theMainObject программе вызова как void *.

  • DiscoverObject имеет несколько методов и создает экземплярыдругие классы находятся в отдельных cpp и .h.Один конкретный метод с именем Hello (), который делает то, что вы ожидаете, он печатает тестовое сообщение "привет" ..


tester.cpp

  • Получает дескриптор библиотеки

  • получает указатель функции на функцию, которая возвращает theMainObject.

  • Выполняет функцию (указатель) и преобразует возвращаемый адрес из void * в DISCOVER_NS :: DiscoverObject * aDiscoverObject.

  • Запустите aDiscoverObject-> Hello ().


Я компилирую с:

CC = @g ++

gflags = -g3

cflags = -fPIC -Wall -pedantic

lib_linkflags: = -shared -fPIC -lstdc ++ -lrt -lpthread -rdynamic

tester_linkflags: = -ldl -lpthread

определяет = -D_ linux _ -D_DEBUG -D_IPC_ARCH_INTEL = 1 -D_THREAD_SAFE


Теперь, когда я компилирую, я получаю этиошибки: * Tester.cpp: 142: неопределенная ссылка на `Discover_NS :: DiscoverObject :: hello () '*

Я также получаю кучу других неопределенных ссылочных ошибок из Discover.so, например: *explore.so: неопределенная ссылка на `Discover_NS :: DeviceList :: ~ DeviceList () *


Я попытался сделать практически все в SO extern" C ".Без разницы.

Я попытался поместить ввескан.cpp в виде операторов, которые выглядят так: extern void Discover_NS :: OtherClass :: method (args);но это дает мне ошибки об ошибках "объявление вне класса не является дефиницией".


Я знаю, что это поможет увидеть код, но мне нужно время, чтобы вынуть что-то маленькое для публикации.

Кто-нибудь может предложить идеи для решения этой проблемы?

Спасибо,

Уэс

Решение Дмитрия было не совсем все исправление, но было необходимым элементом врешение.При проверке моего make-файла я обнаружил пару непреднамеренно дублированных строк, которые я удалил, и две «опечатки», где у меня был неправильный путь для -o, закодированных в этапы компиляции.Прерванные шаги скомпилированы logger.cpp и RemException.cpp:

./common/logger.o : ./common/logger.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  
        -I ./EdgeIO  -I ./Discover   
        -o ./common/Debug/logger.o   <+++++++++ path to .o was wrong
        ./common/logger.cpp   2>&1  | tee ./RemKonTester/logger.ERR

Тогда я обнаружил настоящую ошибку.Я полностью упустил тот факт, что я не собирал все мои .cpp в каталоге Discover !.Потребовался хороший час, чтобы удалить все придирки, но теперь она отлично компилирует из make-файла.

НОВАЯ ВЕРСИЯ ОРИГИНАЛЬНОГО ВОПРОСА: Теперь я знаю, что это будет работать через make-файл, как мне поговорить?Затметься сделать то же самое, что делает make-файл?

Спасибо, Дмитрий.

Уэс

Ну, моя проблема все еще здесь.

У меня есть код, скомпилированный с Дмитрием (@Dmitry)предложения на месте.Только они, кажется, вызывают отдельную проблему.Я хочу, чтобы мои библиотеки динамически связывались с основной тестовой программой во время выполнения.Добавление -l Discover -l EdgeIO к ссылке дает все для компиляции, но дает статическое связывание.

FYI, неиспользуемые "пи" так SOимеет число с плавающей запятой и, таким образом, будет компилироваться с поддержкой с плавающей запятой.Требуется, если вызывающий абонент хочет использовать числа с плавающей запятой.Кто-нибудь получил лучший способ заставить g ++ компилировать с включенной плавающей запятой?

После исправления многих ошибок Дмитрий помог мне найти, теперь я получаю такой вывод:

make
./Discover/dllmain.cpp: In function ‘void InitalizeLibraryServices()’:
./Discover/dllmain.cpp:175: warning: unused variable ‘pi’


./EdgeIO/dllMain.cpp: In function ‘void InitalizeLibraryServices()’:
./EdgeIO/dllMain.cpp:158: warning: unused variable ‘pi’


linking RemKonTester
    gflags = -g3
    tstlinkflags = -ldl  -lpthread 
    defines =  -D__linux__   -D_DEBUG   -D_IPC_ARCH_INTEL=1   -D_THREAD_SAFE

./RemKonTester/Debug/RemKonTester.o: In function `main':
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:81: undefined 
    reference to `RemKon_EdgeIO::EdgeIoObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:111: undefined 
    reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:116: undefined 
    reference to `RemKon_Discover::DiscoverObject::SetLogLevel(unsigned int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:117: undefined 
    reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:118: undefined 
    reference to `RemKon_Discover::DiscoverObject::LocalIpAddress(int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:122: undefined 
    reference to `RemKon_Discover::DiscoverObject::RegisterCallback(bool(*)
    (void*), void*)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:123: undefined 
    reference to `RemKon_Discover::DiscoverObject::Search()'

collect2: ld returned 1 exit status

Iполучить тот же набор сообщений об ошибках из Eclipse.

RemKonTester.cpp включает в себя все .h, где эти элементы объявлены.Я попробовал их с объявлениями extern "C" и не.

Надеясь на помощь,

Wes

Ответы [ 2 ]

5 голосов
/ 06 апреля 2011

Кажется, ваша проблема в позиции -l<library>:

$(CC)  $(gflags)  $(tstlinkflags) $(defines)      -L ./Debug    -ldiscover   
        -ledgeio -o ./Debug/RemKonTester  ./RemKonTester/Debug/RemKonTester.o  
        ./RemKonTester/Debug/logger.o  ./RemKonTester/Debug/libraryClass.o   
        2>&1  | tee ./RemKonTester/make.ERR

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

См. man ld (в частности, опция -l) для дополнительной информации:

-l namespec

...

Компоновщик будет искать архив только один раз в том месте, где он указан в командной строке.Если архив определяет символ, который не был определен в каком-либо объекте, который появился перед архивом в командной строке, компоновщик будет включать соответствующий файл (ы) из архива.Однако неопределенный символ в объекте, появляющемся позже в командной строке, не заставит компоновщик снова выполнить поиск в архиве.

Это должно работать для вас:

$(CC) $ (gflags) $ (tstlinkflags) $ (определяет) -L ./Debug -o ./Debug/RemKonTester ./RemKonTester/Debug/RemKonTester.o ./RemKonTester/Debug/logger.o ./RemKonTester/Debug/libraryClass.o -ldiscover -ledgeio 2> & 1 |tee ./RemKonTester/make.ERR

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

0 голосов
/ 06 апреля 2011

РЕДАКТИРОВАНИЕ: Наконец-то разобрался с «редактором».Сделано это красивее.wjm

Извините за задержку.Вчера вечером мне пришлось убрать упавшее дерево с моего переднего двора.

Примечание: я меняю несколько имен в оригинальной записке, чтобы сделать их короче.В этом ответе все прописано.


g ++ output ...

$ make
./EdgeIO/dllMain.cpp: In function ‘void InitalizeLibraryServices()’:
./EdgeIO/dllMain.cpp:158: warning: unused variable ‘pi’
./Discover/dllmain.cpp: In function ‘void InitalizeLibraryServices()’:
./Discover/dllmain.cpp:174: warning: unused variable ‘pi’
./RemKonTester/RemKonTester.cpp: In function ‘int main(int, char**)’:
./RemKonTester/RemKonTester.cpp:130: warning: ISO C++ forbids casting between     
pointer-to-function and pointer-to-object
./RemKonTester/RemKonTester.cpp:152: warning: unused variable ‘searchResp’
./RemKonTester/libraryClass.cpp: In member function ‘int 
library::AttachLibrary()’:
./RemKonTester/libraryClass.cpp:132: warning: ISO C++ forbids casting between 
pointer-to-function and pointer-to-object
./RemKonTester/libraryClass.cpp:154: warning: ISO C++ forbids casting between 
pointer-to-function and pointer-to-object
./RemKonTester/Debug/RemKonTester.o: In function `main': 
/home/wmiller/Projects/Eclipse/
./RemKonTester/RemKonTester.cpp:142: undefined reference to 
`RemKon_Discover::DiscoverObject::hello()'
collect2: ld returned 1 exit status
gflags = -g3
tstlinkflags = -ldl  -lpthread
defines =  -D__linux__   -D_DEBUG   -D_IPC_ARCH_INTEL=1   -D_THREAD_SAFE
./Debug/libdiscover.so: undefined reference to     
`RemKon_Discover::RemKonDeviceList::~RemKonDeviceList()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::ClientPort(unsigned short)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::PayloadSize(unsigned int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::Socket() const'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::Count() const'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemException::~RemException()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::UDPbinder()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::ListenTimeOut(int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::ServerPort(unsigned short)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::Next()'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::Log(char 
const*, ...)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::UDPlisten(unsigned char*, int*, sockaddr_in*, int*)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemException::RemException()'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::VerboseLogging()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::RegisterCallbackFunction(void (*)(void*, unsigned 
char*, int), void*)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::First()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::TestData(unsigned int, unsigned int, unsigned char*, 
unsigned int)'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::Logging()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::MessageLength(int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::LocalIpAddress(int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::UDPsend()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::DiscoverObject::LocalIpAddress() const'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::SetBroadcastMode()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::MakeMacAddressString(unsigned char*, char*)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::RemKonDeviceList()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::New()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::ActivateLogging(unsigned int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::RemSocket()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::Payload(unsigned int)'
collect2: ld returned 1 exit status

И это make-файл.Извините, я не говорю, что это хорошо, так что make-файл функционален, а не хорош.

CC = @g++
gflags = -g3
cflags = -fPIC -Wall -pedantic
liblinkflags := -shared -fPIC -lstdc++ -lrt -lpthread -rdynamic
tstlinkflags := -ldl  -lpthread
defines = -D__linux__   -D_DEBUG   -D_IPC_ARCH_INTEL=1   -D_THREAD_SAFE


all : clean edgeio discover tester


############################################

edgeio : ./EdgeIO/dllMain.o ./EdgeIO/EdgeIO.o
$(CC) $(gflags)  $(liblinkflags) $(defines)    -Wl,-soname,./Debug
    /libedgeio.so.1  -o ./Debug/libedgeio.so.1.0 ./EdgeIO/Debug/edgeio.o  
    ./EdgeIO/Debug/dllmain.o    2>&1  | tee ./EdgeIO/make.ERR
            @cd ./Debug; ln -sf libedgeio.so.1.0    libedgeio.so
        @cd ./Debug; ln -sf libedgeio.so.1.0    libedgeio.so.1

./EdgeIO/dllMain.o : ./EdgeIO/dllMain.cpp
        $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
    -I ./Discover   -o./EdgeIO/Debug/dllmain.o  ./EdgeIO/dllMain.cpp   2>&1  
    | tee ./EdgeIO/dllmain.ERR

./EdgeIO/EdgeIO.o : ./EdgeIO/EdgeIO.cpp
    $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
    -I ./Discover   -o./EdgeIO/Debug/edgeio.o  ./EdgeIO/EdgeIO.cpp     2>&1  | 
    tee ./EdgeIO/EdgeIO.ERR

############################################

discover : ./Discover/Discover.o ./Discover/dllmain.o
    $(CC) $(gflags)  $(liblinkflags) $(defines)    -Wl,-soname,./Debug
        /libdiscover.so.1  -o ./Debug/libdiscover.so.1.0          ./Discover/Debug
        /Discover.o  ./Discover/Debug/dllmain.o    2>&1  | tee ./Discover/make.ERR
    @cd ./Debug; ln -sf libdiscover.so.1.0  libdiscover.so
    @cd ./Debug; ln -sf libdiscover.so.1.0  libdiscover.so.1

./Discover/Discover.o : ./Discover/Discover.cpp
    $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
    -I ./Discover   -o./Discover/Debug/Discover.o  ./Discover/Discover.cpp  
     2>&1  | tee ./Discover/Discover.ERR

./Discover/dllmain.o : ./Discover/dllmain.cpp
        $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover   -o./Discover/Debug/dllmain.o  ./Discover/dllmain.cpp   
        2>&1  | tee ./Discover/dllmain.ERR

############################################

tester : ./RemKonTester/RemKonTester.o ./common/logger.o  ./RemKonTester
        /libraryClass.o    ./common/RemException.o
    $(CC)  $(gflags)  $(tstlinkflags) $(defines)       
        -L ./Debug -o ./Debug/RemKonTester  ./RemKonTester/Debug
        /RemKonTester.o  ./RemKonTester/Debug/logger.o  ./RemKonTester/Debug
        /libraryClass.o   2>&1  | tee ./RemKonTester/make.ERR

    @echo "gflags = $(gflags)"   2>&1  | tee ./RemKonTester/make.ERR
    @echo "tstlinkflags = $(tstlinkflags)"   2>&1  | tee ./RemKonTester/make.ERR
    @echo "defines =  $(defines)"   2>&1  | tee ./RemKonTester/make.ERR

    $(CC)  $(gflags)  $(tstlinkflags) $(defines)      -L ./Debug    -ldiscover   
        -ledgeio -o ./Debug/RemKonTester  ./RemKonTester/Debug/RemKonTester.o  
        ./RemKonTester/Debug/logger.o  ./RemKonTester/Debug/libraryClass.o   
        2>&1  | tee ./RemKonTester/make.ERR

./RemKonTester/RemKonTester.o : ./RemKonTester/RemKonTester.cpp
    $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
        -I ./Discover   -o ./RemKonTester/Debug/RemKonTester.o   ./RemKonTester
        /RemKonTester.cpp   2>&1  | tee ./RemKonTester/RemKonTester.ERR

./common/logger.o : ./common/logger.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover    -o ./RemKonTester/Debug/logger.o  ./common/logger.cpp
        2>&1  | tee ./RemKonTester/logger.ERR

./RemKonTester/libraryClass.o : ./RemKonTester/libraryClass.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover    -o ./RemKonTester/Debug/libraryClass.o 
        ./RemKonTester/libraryClass.cpp   2>&1  | tee ./RemKonTester
        /libraryClass.ERR

./common/RemException.o : ./common/RemException.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover    -o ./RemKonTester/Debug/RemException.o ./common
        /RemException.cpp   2>&1  | tee ./RemKonTester/RemException.ERR


############################################

clean :
    @rm -f *.ERR
    @rm -f ./common/*.ERR
    @rm -f ./EdgeIO/*.ERR
    @rm -f ./Discover/*.ERR
    @rm -f ./RemKonTester/*.ERR

    @rm -f QEMACRO*
    @rm -f ./common/EdgeIO/QEMACRO*
    @rm -f ./EdgeIO/QEMACRO*
    @rm -f ./Discover/QEMACRO*
    @rm -f ./RemKonTester/QEMACRO*

    @rm -f ./Debug/*.o
    @rm -f ./common/Debug/*.o
    @rm -f ./EdgeIO/Debug/*.o
    @rm -f ./Discover/Debug/*.o
    @rm -f ./RemKonTester/Debug/*.o

    @rm -f ./Debug/*.log
    @rm -f ./common/Debug/*.log
    @rm -f ./EdgeIO/Debug/*.log
    @rm -f ./Discover/Debug/*.log
    @rm -f ./RemKonTester/Debug/*.log

    @rm -f ./Debug/*.so*

############################################

Спасибо,

Уэс

...