2010-09-10 5 views
2

Я пытаюсь создать общую библиотеку в Windows. Я могу создать эту общую библиотеку в linux, но в окнах я получаю ошибки компоновщика. Я использую компилятор MinGW G ++ 4.5. Сначала я представлю исходный код примера на linux, а затем представим файл, который я попытался изменить в окнах.с использованием внешней переменной в C++ в общей библиотеке - создание общей библиотеки (dll) с использованием MinGW g ++

/home/nxd/Progs/C++/shared-lib>cat lib_interface.h 

#ifndef LIBINTERFACE_H 
#define LIBINTERFACE_H 

int func(int a); 

#endif /* LIBINTERFACE_H */ 
/home/nxd/Progs/C++/shared-lib>cat sh_lib.cpp 
extern int b; 

int func(int a) 
{ 
return a+b; 
} 
/home/nxd/Progs/C++/shared-lib>cat main.cpp 
#include <iostream> 
#include "lib_interface.h" 

int b; 

int main() 
{ 
b=10; 
std::cout << func(20) << std::endl; 
} 

/home/nxd/Progs/C++/shared-lib>cat Makefile 
OBJS = main.o sh_lib.o 

test: main.o libshared.so 
g++ -L. [email protected] main.o -lshared 

main.o: main.cpp lib_interface.h 
g++ -c -Wall -fPIC $< 

sh_lib.o: sh_lib.cpp lib_interface.h 
g++ -c -Wall -fPIC $< 

libshared.so: sh_lib.o 
ld -shared -soname=libshared.so -o libshared.so.1 $< 
ln -s libshared.so.1 libshared.so 

.PHONY: clean 

clean: 
rm *.o *.so *.so.1 
/home/nxd/Progs/C++/shared-lib>make 
g++ -c -Wall -fPIC main.cpp 
g++ -c -Wall -fPIC sh_lib.cpp 
ld -shared -soname=libshared.so -o libshared.so.1 sh_lib.o 
ln -s libshared.so.1 libshared.so 
g++ -L. -otest main.o -lshared 
/home/nxd/Progs/C++/shared-lib>LD_LIBRARY_PATH=. ./test 
30 

Я попытался сделать общую библиотеку из sh_lib.cpp с использованием MinGW г ++ на Windows. Причина, по которой так много комментариев, объясняется многими вещами, которые я пробовал, прежде чем решил опубликовать это.

/home/nxd>cat sh_lib.cpp 
//extern "C" __declspec(dllimport) int b; 
//#ifdef __cplusplus 
//extern "C" { 
//#endif 

__declspec(dllimport) extern int b; 
//__declspec(dllimport) int b; 
//extern int b; 

//#ifdef __cplusplus 
//} 
//#endif 

int func(int a) 
{ 
return a+b; 
} 

Ниже приведена соответствующая часть файла Makefile с различными твиками. Параметры, переданные компоновщику, который вы видите ниже, были добавлены один за другим, чтобы попытаться избавиться от ошибки связи. Приведенная ниже команда ld заключалась в том, чтобы убедиться, что компоновщик действительно получает варианты. Предыдущий дефис говорит make выполнить следующую команду, даже если текущий имеет ошибки.

sh_lib.o: sh_lib.cpp lib_interface.h 
g++ -c -Wall -fPIC $< 

libshared.so: sh_lib.o 
-ld -shared --enable-auto-import --unresolved-symbols=ignore-in-shared-libs -soname=libshared.so --allow-shlib-undefined -o libshared.so.1 $< 
g++ -shared -Wl,--unresolved-symbols=ignore-in-shared-libs -Wl,--enable-auto-import -Wl,--allow-shlib-undefined -Wl,-soname,libshared.so -o libshared.so.1 $< 

Мой вопрос: как я могу скомпилировать sh_lib.cpp в DLL, используя внешнюю переменную, как, как она работает в Linux ?. Я прочитал статью stackoverflow: Can't access variable in C++ DLL from a C app, но «я думаю» между двумя случаями есть тонкая разница. Там он пытался связать файл, здесь я пытаюсь создать общую библиотеку, используя переменную, для которой хранилище не было выделено (extern), и я хочу сказать компоновщику игнорировать хранилище этой переменной при создании библиотеки - он будет разрешен, когда я свяжусь с exe. В настоящее время я управляю этой проблемой со статической привязкой.

Большое спасибо за вашу помощь заранее.

ответ

2

Я предоставил свой ответ по электронной почте (потому что исходный плакат повторил свой вопрос по электронной почте в список, который я следую) в комплекте с модифицированным образцом, который работает так, как он хотел. См. http://mingw-users.1079350.n2.nabble.com/using-an-external-variable-in-C-in-a-shared-library-tp5521039p5521149.html. Я не буду повторять здесь все. Просто некоторые ключевые моменты:

  • declspec (DllImport/dllexport) требуется для переменных, да
  • импортировать переменные из EXE-файла, вы должны относиться к еху как DLL в том смысле, что вы генерируете библиотеку импорта для связывания разделяемой библиотеки с
  • , но на самом деле вы не хотите импортировать переменные из exe, так как это означает, что только exe с этим именем может использовать рассматриваемую разделяемую библиотеку
  • вместо этого, редизайн программное обеспечение не имеет переменных в границах API. Просто имейте в API в библиотеке функцию «зарегистрировать» данные в основном (или где угодно), необходимые для последующих вызовов в библиотеку, а не
  • и фактически, как совет, не используйте переменные в API библиотек, чистый API на основе функций намного приятнее
  • Обратите внимание, что оригинальный плакат использует MinGW, поэтому не беспокойтесь, комментируя, если у вас есть опыт работы только с MSVC. Они могут сильно отличаться по некоторым ключевым аспектам здесь
  • наконец-то, я действительно не парень из C++, поэтому я говорю из чистого аспекта C, извините. C++ классы и т. Д., Безусловно, усложнят ситуацию и вызовут еще более неприятные различия между gcc на Linux/gcc на Windows (MinGW)/MSVC/и другие
0

вы не говорите, что ошибка (ы) вы получаете, но я вижу, по крайней мере, две вещи в источнике, который может привести к хаосу:

  • __declspec (DllImport) INT B: с этим утверждением , вы говорите, что b необходимо импортировать (из библиотеки библиотеки импорта для dll), но это не сработает, так как вы хотите использовать «b» из вашего exe. (редактирование начинается здесь) Сначала я думал, что «extern int b» сделает это, но это не сработает: компоновщик должен знать, где b, чтобы иметь возможность создать dll, вот как это сделать работает на Windows (к моему пониманию, пожалуйста, кто-то поправьте меня, если я ошибаюсь). Высказывание «extern int» компилятору похоже на то, что «эй есть где-то внутри, но это не в этом блоке компиляции, не волнуйся, что компоновщик это выяснит». И есть проблема: компоновщик ее не находит. Я не вижу другого выбора, кроме как переписать a, чтобы взять b в качестве аргумента или избавиться от «extern», так что «b» находится в dll.

  • int func (int a): имеет в основном такую ​​же проблему, он должен быть экспортирован из dll и импортирован в основной исполняемый файл;

пример заголовка:

#ifdef BUILD_DLL 
    #define MYDLL __declspec(dllexport) 
#else 
    #define MYDLL __declspec(dllimport) 
#endif 

MYDLL int func(int a); 

При создании библиотеки DLL, можно определить BUILD_DLL (передать -DBUILD_DLL к НКУ) и имеет линкер создать библиотеку импорта (передать -Wl, - из-Implib , libmylib.a).

При создании исполняемого файла ничего не задайте, и макрос разрешит dllimport, поэтому компоновщик знает, что он должен найти func где-то еще, а именно в библиотеке импорта для dll (pass -lmylib и в конечном счете -L/path/to/dir/where/lib/is)

+0

Я начал «sh_lib.cpp» с extern int b; Но когда я пытаюсь создать общую библиотеку, я получаю сообщение об ошибке «undefined reference to b». Я не получаю эту ошибку в Linux. > Остается вопрос, имеет ли смысл внешний мир,> могут быть лучшие варианты. Ну, исходный пример - это компилятор, который я разрабатываю - исходный код http://sourceforge.net/projects/xtcc в qscript-0.7.tar.gz. Глобальная переменная - это «список вопросов», необходимый в средах среды выполнения и компиляции , – Neil

+0

Я действительно не думал об этом, отредактировал ответ: я не уверен, что это может когда-либо работать с dll .. надеюсь, кто-то еще может дать более глубокое понимание? – stijn