当前位置:  开发笔记 > 运维 > 正文

在C中创建模块系统(动态加载)

如何解决《在C中创建模块系统(动态加载)》经验,为你挑选了3个好方法。

如何在运行时加载编译的C代码,然后调用其中的函数?不像简单地调用exec().

编辑:加载模块的程序在C中.



1> bortzmeyer..:

dlopen是要走的路.这里有一些例子:

使用dlopen加载插件:

#include 
...
int
main (const int argc, const char *argv[])
{

  char *plugin_name;
  char file_name[80];
  void *plugin;
  ...
  plugin = dlopen(file_name, RTLD_NOW);
  if (!plugin)
  {
     fatal("Cannot load %s: %s", plugin_name, dlerror ());
  }

编译以上内容:

% cc  -ldl -o program program.o 

然后,假设插件的API:

/* The functions we will find in the plugin */
typedef void (*init_f) ();
init_f init;
typedef int (*query_f) ();
query_f query;

在插件中查找init()的地址:

init = dlsym(plugin, "init");
result = dlerror();
if (result)
{
   fatal("Cannot find init in %s: %s", plugin_name, result);
}
init();

使用另一个函数query(),它返回一个值:

query = dlsym (plugin, "query");
result = dlerror();
if (result)
{
    fatal("Cannot find query in %s: %s", plugin_name, result);
}
printf("Result of plugin %s is %d\n", plugin_name, query ());

您可以获取完整的例子就行.



2> Robert Gambl..:

在Linux/UNIX中,您可以使用POSIX dlopen/ dlsym/ dlerror/ dlclose函数动态打开共享库并访问它们提供的符号(包括函数),有关详细信息,请参见手册页.



3> erisu..:

看到这个问题已得到解答,但认为对此主题感兴趣的其他人可能会欣赏来自旧的基于插件的应用程序的跨平台示例.该示例适用于win32或linux,并在文件参数中指定的动态加载的.so或.dll中调用并调用名为"constructor"的函数.示例是在c ++中,但c的过程应该相同.

//firstly the includes
#if !defined WIN32
   #include 
   #include 
#else
   #include 
#endif

//define the plugin's constructor function type named PConst
typedef tcnplugin* (*PConst)(tcnplugin*,tcnplugin*,HANDLE);

//loads a single specified tcnplugin,allmychildren[0] = null plugin
int tcnplugin::loadplugin(char *file) {
    tcnplugin *hpi;
#if defined WIN32               //Load library windows style
    HINSTANCE hplugin=LoadLibrary(file);
    if (hplugin != NULL) {
            PConst pinconstruct = (PConst)GetProcAddress(hplugin,"construct");
#else                                   //Load it nix style
    void * hplugin=dlopen(file,RTLD_NOW);
    if (hplugin != NULL) {
            PConst pinconstruct = (PConst)dlsym(hplugin,"construct");
#endif   
            if (pinconstruct != NULL) { //Try to call constructor function in dynamically loaded file, which returns a pointer to an instance of the plugin's class
                    hpi = pinconstruct(this, this, hstdout);
            } else {
                    piprintf("Cannot find constructor export in plugin!\n");
                    return 0;
            }
    } else {
            piprintf("Cannot open plugin!\n");
#if !defined WIN32
            perror(dlerror());
#endif
            return 0;
    }
    return addchild(hpi); //add pointer to plugin's class to our list of plugins
}

可能还会提到,如果要调用的函数模块是用c ++编写的,则必须使用extern"C"声明函数,例如:

extern "C" pcparport * construct(tcnplugin *tcnptr,tcnplugin *parent) {
    return new pcparport(tcnptr,parent,"PCPARPORT",0,1);
}

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有