我正在尝试在Windows上创建一个共享库。我能够在Linux上创建这个共享库但在Windows上我得到链接器错误。我正在使用MinGW G ++ 4.5编译器。我将首先在linux上的示例中提供源代码,然后呈现我试图在Windows上更改的文件。
/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. -o$@ 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
我尝试在Windows上使用MinGW g ++从sh_lib.cpp创建一个共享库。有这么多评论的原因是因为在我决定发布之前我尝试了很多东西。
/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 $<
我的问题:如何使用extern变量将sh_lib.cpp编译成dll,就像它在linux中的工作方式一样?我确实读过stackoverflow文章: Can't access variable in C++ DLL from a C app,但“我认为”这两种情况之间存在细微差别。在那里他试图链接文件,这里我试图创建一个共享库,使用一个尚未分配存储的变量(extern),我想告诉链接器在创建库时忽略这个变量的存储 - 当我与exe链接时,它将被解决。我目前正在使用静态链接来解决这个问题。
非常感谢您的帮助。
答案 0 :(得分:2)
我在电子邮件中提供了我的答案(因为原始海报在电子邮件中将他的问题重复到我所遵循的列表中),完成了修改后的样本源,可以按照自己的意愿运行。见http://mingw-users.1079350.n2.nabble.com/using-an-external-variable-in-C-in-a-shared-library-tp5521039p5521149.html。我不会在这里重复整个事情。只是一些关键点:
答案 1 :(得分:0)
你没有说出你得到了什么错误,但我发现源中至少有两件可能造成破坏的事情:
__ declspec(dllimport)int b:使用此语句,您说b必须导入(从dll的导入库)库,但由于您要使用'b',这将无效来自你的exe。 (编辑从这里开始)起初我认为'extern int b'会这样做,但那也行不通:链接器需要知道b在哪里才能创建dll,这就是这个适用于Windows(据我所知,如果我错了,请有人纠正我)。对编译器说'extern int'就像是说'嘿,某个地方有一个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传递给gcc)并让链接器创建一个导入库(传递-Wl, - out-implib,libmylib.a)。
构建可执行文件时,不要定义任何额外内容,宏会解析为dllimport,因此链接器知道它必须在其他地方找到func,即在dll的导入库中(传递-lmylib,最后是-L / path / to) /目录/其中/ LIB /是)