在OS X上使用C语言中的dlopen()动态库访问主程序全局变量

8
我正在维护一个小应用程序,它具有类似插件的功能,通过运行时加载的动态模块来实现。
具体而言,由于它是一个Gtk+应用程序,我正在使用gmodule,但问题同样适用于基于dlfcn.h / dlopen()的动态库加载。
我的主程序有一个单一的全局结构变量,保存一些全局信息。我希望这些信息能够在动态加载的插件中定义的函数中使用。
在Linux上,我可以直接引用这个全局变量 - 这很有效,我猜想gcc或链接器会负责将全局变量从主程序导出到动态库。
问题是,在Mac OS X上这种方法不起作用。是否有办法在OS X上实现这个目标?
如果没有,是否有更好的方式将全局信息公开给动态加载的库?

顺便提一下,这里有一些简化问题的示例代码:http://pastie.org/749794 - shevron
2个回答

9

将全局变量放在main.c中,并在共享对象中声明为extern,然后尝试以下操作:

MACOSX_DEPLOYMENT_TARGET=10.3 ld -dylib -undefined dynamic_lookup -o multiply.so multiply.o

或者

MACOSX_DEPLOYMENT_TARGET=10.3 libtool -dynamic -undefined dynamic_lookup -o multiply.so multiply.o

在我的Mac OS X 10.4上它可以正常工作。


谢谢,这个可行!虽然我没有使用TAGET环境变量,但我猜那与此不太相关。现在看看如何将其集成到我的Makefile中! - shevron
1
它还可以直接从gcc工作:gcc -Wall -g -fPIC -c multiply.c gcc -shared -Wl,-undefined,dynamic_lookup -o multiply.so multiply.o - shevron

3

由于您声明了

int global;

在multiply.h头文件中,DLL和主程序都有自己的副本。相反,应该在main.c中声明全局变量。
int global;

在 multiply.c 文件中,将其声明为 extern:

extern int global;

如果您使用-rdynamic选项将main.cpp与其他文件链接,那么可执行文件的符号将会被导出到DLL中。

我在Linux下测试过,可以正常工作,但是我没有测试MacOS。由于您的示例代码在Linux上也无法正常工作,所以我认为这可能是问题所在。


据我所知,在OS X上不支持-rdynamic。无论如何,当我尝试链接multiply.o时,会出现“_global”未定义的错误。 - shevron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接