当加载共享库通过函数dlopen()
打开时,有没有办法让它在主程序中调用函数?加载的库函数如何在主应用程序中调用符号?
回答
代码(的lib):与
gcc -shared -olibdlo.so dlo.c
#include <stdio.h>
// function is defined in main program
void callb(void);
void test(void) {
printf("here, in lib\n");
callb();
}
编译
这里的主程序代码(从dlopen手册页复制并调整):
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void callb(void) {
printf("here, i'm back\n");
}
int
main(int argc, char **argv)
{
void *handle;
void (*test)(void);
char *error;
handle = dlopen("libdlo.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
*(void **) (&test) = dlsym(handle, "test");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
(*test)();
dlclose(handle);
exit(EXIT_SUCCESS);
}
使用Build
gcc -ldl -rdynamic main.c
输出:
[[email protected] dlopen]$ LD_LIBRARY_PATH=. ./a.out
here, in lib
here, i'm back
[[email protected] dlopen]$
的-rdynamic
选项把在动态符号表中的所有码元(其被映射到存储器中),不仅使用的符号的名称。详细了解它here。当然,你也可以提供函数指针(或者函数指针的结构)来定义库和主程序之间的接口。这实际上是我可能选择的方法。我从其他人那里听说,在Windows中做-rdynamic
并不是那么容易,它也会使库和主程序之间的通信变得更清晰(你可以精确地控制可以调用的内容而不是),但它也需要更多的管家。
是的,如果您为库提供了一个指向该函数的指针,我相信该库将能够在主程序中运行/执行该函数。
下面是一个例子,并没有编译它所以要小心)dlo.c的
/* in main app */
/* define your function */
int do_it(char arg1, char arg2);
int do_it(char arg1, char arg2){
/* do it! */
return 1;
}
/* some where else in main app (init maybe?) provide the pointer */
LIB_set_do_it(&do_it);
/** END MAIN CODE ***/
/* in LIBRARY */
int (*LIB_do_it_ptr)(char, char) = NULL;
void LIB_set_do_it(int (*do_it_ptr)(char, char)){
LIB_do_it_ptr = do_it_ptr;
}
int LIB_do_it(){
char arg1, arg2;
/* do something to the args
...
... */
return LIB_do_it_ptr(arg1, arg2);
}
do_it_ptr需要一个指向需要3个字符参数的函数的指针;你为只有2个字符参数的函数分配函数指针。 doit()的extern声明几乎不需要。 do_it_ptr不是必需的;你可以在你当前传递do_it_ptr的地方通过名字传递do_it。等等! – 2008-12-25 06:18:52
如@litb所述,dlopen()
函数主要在使用ELF格式对象文件的系统上提供。它相当强大,并且可以让您控制是否可以从主程序中满足加载库引用的符号,并且通常会让它们满意。并非所有的共享库加载系统都是灵活的 - 请注意是否需要移植代码。
@hhafez概述的回调机制现在可以工作,该代码中的扭结被理顺了。
- 1. 如何在调试Visual C++程序时禁用符号加载?
- 2. 如何在主应用程序中使用数组参数调用函数?
- 3. 共享库(.so)如何调用在其加载程序中实现的函数?
- 4. 远程调试MVC 6应用程序:符号未加载。
- 5. 如何在Web应用程序中加载国家数据库
- 6. 信号处理程序没有在主函数中调用
- 7. 引导加载程序函数调用
- 8. 如何从Flex中的主应用程序加载子应用程序
- 9. 从Arduino的库中调用主程序中的函数
- 10. 如何在ajax应用程序中加载Angularjs应用程序?
- 11. 如何在控制台应用程序主要方法中调用javascript函数
- 12. 数据库如何加载到应用程序中?
- 13. 如何在聊天应用程序中添加表情符号
- 14. 如何在Android应用程序中重复调用函数?
- 15. 如何在Cordova中安装应用程序时调用函数
- 16. 无法在VS 2010上加载Silverlight应用程序的符号
- 17. 如何从主程序中的函数调用列表?
- 18. 如何在MFC应用程序中加载VC++ CLR库?
- 19. 如何在我的Flex应用程序的swfLoader中加载的swf文件中调用actionscript函数?
- 20. 如何在应用程序加载时调用一个xib?
- 21. 如何在C++中调用主函数
- 22. 如何不断调用WPF应用程序中的函数
- 23. 如何在Metro应用程序中插入数学符号
- 24. 如何在外部node.js应用程序中重载函数?
- 25. 如何从PluginKit加载数据库应用程序
- 26. 如何在网络应用程序启动时在openshift中加载函数
- 27. 如何在VCL窗体应用程序中调用和调用函数
- 28. 如何调试到iOS应用程序的XIB加载过程?
- 29. 使用gdb跟踪外国的android程序或应用程序 - 加载符号?
- 30. 如何在MATLAB中调用主函数中的函数?
下面的答案在回答这个问题方面做得很好,但我必须问 - 你能否解释这个要求的更广泛的背景?当我发现需要这样做时,要么是构建一个可扩展性/插件模型,要么是因为我的程序不是很好的考虑因素。 – reuben 2008-12-25 06:18:56
它也可以用于倒置控制,不是吗?定义应用程序在库中的流程,而实际的实现在主应用程序中 – hhafez 2008-12-25 11:19:16
想象一下Perl XS模块。它需要使用低级别的Perl函数(比如说newSViv()从一个整数中创建一个SV);如果模块使用Perl的newSViv()函数,而不是将其自己的副本嵌入到模块的共享对象中,则很方便。此外,代码需要标准的C库。 – 2008-12-25 19:35:29