Как правильно связать статическую библиотеку с помощью g++

Решение. Спасибо всем, кто прокомментировал эту проблему, но я решил ее на другом форуме и решил опубликовать ответ здесь для всех, у кого возникла такая же проблема.

Итак, я предполагаю, что только динамические библиотеки используют __declspec(dllexport), поэтому, когда вы пытаетесь создать статическую библиотеку, методы экспортируются (имена должны быть искажены, чтобы быть совместимыми с С++), поэтому при объявлении extern "C" __declspec.... вы получаете имена методов, которые не распознаются при попытке статического связывания.

Итак, простое исправление..... удалите __declspec

У меня есть 2 проекта, один - статическая библиотека, другой - просто приложение win32.

Я просто хочу включить библиотеку, которую я создал, в свое приложение win32, однако g++ продолжает выдавать мне эту ошибку:

../MyLib/TestClass.h:16: неопределенная ссылка на `imp__ZTV9TestClass'

Это ошибка, которую я получаю при попытке скомпилировать приложение, хотя этот файл является частью библиотеки.

Я попытался создать максимально упрощенную версию этого проекта, пытаясь найти ошибку.

Вот исходные файлы для обоих проектов:

MyLib.h — это основной включаемый файл, с помощью которого клиенты могут ссылаться на функции в библиотеке.

#ifndef MYLIB_H
#define MYLIB_H

#include "libexport.h"
#include "TestClass.h"

#endif  /* MYLIB_H */

libexport.h — довольно общий файл для определения ключевых слов импорта/экспорта.

#ifndef LIBEXPORT_H
#define LIBEXPORT_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef LIB
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
}
#endif

#endif  /* LIBEXPORT_H */

ТестКласс.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include "libexport.h"

class DLL_EXPORT TestClass
{
public:
    TestClass() {};
    virtual ~TestClass() {};

    void TestFunc();
};

#endif  /* TESTCLASS_H */

TestClass.cpp

#define LIB

#include <stdio.h>
#include "TestClass.h"

void TestClass::TestFunc()
{
    printf("This function was called from within the library.\n");
}

И, наконец, приложение win32, реализующее библиотеку:

Main.cpp

#include <windows.h>
#include "../MyLib/MyLib.h"

#pragma comment(lib, "libmylib.a")

int __stdcall WinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPSTR lpCmdLine,
                      int nCmdShow)
{

    TestClass *myClass = new TestClass();

    delete myClass;
    myClass = 0;

    return 0;
}

Библиотека компилируется без ошибок, однако вот вывод при компиляции основного приложения:

g++.exe    -c -g -MMD -MP -MF build/Debug/MinGW-Windows/main.o.d -o build/Debug/MinGW-Windows/main.o main.cpp
mkdir -p dist/Debug/MinGW-Windows
g++.exe     -mwindows -o dist/Debug/MinGW-Windows/testclient build/Debug/MinGW-Windows/main.o -L../MyLib/dist/Debug/MinGW-Windows -lmylib 
build/Debug/MinGW-Windows/main.o: In function `TestClass':
C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:16: undefined reference to `_imp___ZTV9TestClass'
make[2]: Leaving directory `/c/Users/Nick/Documents/NetBeansProjects/TestClient'
build/Debug/MinGW-Windows/main.o: In function `~TestClass':
make[1]: Leaving directory `/c/Users/Nick/Documents/NetBeansProjects/TestClient'
C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:17: undefined reference to `_imp___ZTV9TestClass'
collect2: ld returned 1 exit status
make[2]: *** [dist/Debug/MinGW-Windows/testclient.exe] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2


BUILD FAILED (exit value 2, total time: 1s)

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

g++.exe -lmylib -mwindows -o dist/Debug/MinGW-Windows/testclient build/Debug/MinGW-Windows/main.o -L../MyLib/dist/Debug/MinGW-Windows -lmylib 
build/Debug/MinGW-Windows/main.o: In function `TestClass':
C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:16: undefined reference to `_imp___ZTV9TestClass'

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


person DivXZero    schedule 31.01.2012    source источник
comment
Это статическая библиотека, поэтому попробуйте просто libmylib.a (без -l) вместо -lmylib. Возможно, вам придется указать полный путь: build/Debug/libmylib.a или любой другой.   -  person TonyK    schedule 31.01.2012
comment
Похоже, это производит то же самое: g++.exe -mwindows ../MyLib/dist/Debug/MinGW-Windows/libmylib.a -o dist/Debug/MinGW-Windows/testclient build/Debug/MinGW-Windows/main .o -L../MyLib/dist/Debug/MinGW-Windows -lmylib make[2]: Выход из каталога /c/Users/Nick/Documents/NetBeansProjects/TestClient' make[1]: Leaving directory /c/Users/Nick/Documents/NetBeansProjects/TestClient' build/Debug/MinGW-Windows/main.o : В функции TestClass': C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:16: undefined reference to _imp___ZTV9TestClass'   -  person DivXZero    schedule 31.01.2012
comment
порядок связывания объектов и ar-архивов тоже важен   -  person PlasmaHH    schedule 31.01.2012
comment
нет, это ЕСТЬ в конце, я просто сказал, что пробовал это в начале без каких-либо новых результатов, это помогает, если вы посмотрите на предоставленную информацию.   -  person DivXZero    schedule 31.01.2012
comment
Поместите ../MyLib/dist/Debug/MinGW-Windows/libmylib.a после build/Debug/MinGW-Windows/main.o.   -  person TonyK    schedule 31.01.2012
comment
Дает те же результаты: g++.exe -mwindows -o dist/Debug/MinGW-Windows/testclient build/Debug/MinGW-Windows/main.o ../MyLib/dist/Debug/MinGW-Windows/libmylib.a build/ Debug/MinGW-Windows/main.o: В функции TestClass': C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:16: undefined reference to _imp___ZTV9TestClass'   -  person DivXZero    schedule 31.01.2012


Ответы (3)


-L/path/to/library/ и -lName как варианты g++ у меня работали. Не указывайте имя библиотеки в path/to/library .

person TeaOverflow    schedule 31.01.2012
comment
Именно так я указал это в данном примере... -L../MyLib/dist/Debug/MinGW-Windows -lmylib, но он все еще дает ошибку неопределенной ссылки, поэтому я запутался - person DivXZero; 31.01.2012
comment
Ой, извините, наверное, пропустил. mylib зовут libmylib.a? Потому что это то, что предполагает опция -l. - person TeaOverflow; 31.01.2012

Решение. Спасибо всем, кто прокомментировал эту проблему, но я решил ее на другом форуме и решил опубликовать ответ здесь для всех, у кого возникла такая же проблема.

Итак, я предполагаю, что только динамические библиотеки используют __declspec(dllexport), поэтому, когда вы пытаетесь создать статическую библиотеку, методы экспортируются (имена должны быть искажены, чтобы быть совместимыми с C++), поэтому при объявлении extern "C" __declspec.... вы получаете имена методов которые не распознаются при попытке статического связывания.

Итак, простое решение: удалите __declspec

person Community    schedule 31.01.2012

Попробуйте поставить -L и -l перед main.o в командной строке связывания.

person selalerer    schedule 31.01.2012
comment
Не имело значения, по-прежнему получаю ту же ошибку неопределенной ссылки - person DivXZero; 31.01.2012