2012-11-14 53 views
3

它似乎可以在Windows和Linux上正常工作,使用GetProcAddress()或dlsym()来返回一个填充有函数指针的结构,以便从动态库中使用。如何从共享/动态库中加载符号表结构?

...但是,似乎有大量的人提出问题并抱怨铸造void *指向函数指针,并且谈论使用dlfunc,当这种相对简单的方法似乎工作得很好时。

那么,你有什么特别的理由不想这样做吗?

像这样的代码由于某种原因不可移植吗?

我意识到这种方法只适用于共享明确命名的函数和绑定函数,但加载插件这就好,因为我担心......?

header.h:

/* C++ safety & windows support */ 
#ifdef __cplusplus 
    #if _WIN32 || _WIN64 
    #define __EXT extern "C" __declspec(dllexport) 
    #else 
    #define __EXT extern "C" 
    #endif 
#else 
    #if _WIN32 || _WIN64 
    #define __EXT __declspec(dllexport) 
    #else 
    #define __EXT extern 
    #endif 
#endif 

struct a_sym_table { 
    int (* action) (int argc, char *argv[]); 
}; 

__EXT struct a_sym_table liba_symbols; 

由source.c:

int perform_action_lib_a(int argc, char *argv[]) { 
    int rtn = perform_action_lib_b() + perform_action_lib_c(); 
    return(rtn); 
} 

struct a_sym_table liba_symbols = { 
    &perform_action_lib_a 
}; 

编辑:只是为了清楚起见,明显代码负载符号将在不同平台上的不同,但是这种方法允许共享库可以被移植到不同的平台而无需改变。

这就是我在谈论的时候,我问,是否有一个原因,你不会这样做?

我想知道的是,如果有一些很好的理由不构成你的共享库像这样可移植性缘故。

回答

3

您正在访问共享库中的数据。这是dlsym()的用途。动态链接器应该能够处理传递库边界的函数指针。至少在类Unix系统上。我不了解Windows,但是如果某些类型的指针可以工作,而其他类型的指针可以工作,则可以想象很多事情会中断。

当谈到可移植性时,您已经限制为拥有“#if _WIN32 || _WIN64”背后的内容或实现dlsym的系统。这应该已经暗示你正在做的是通过测试来完成工作,而不是遵循一些严格的标准文档。所以你可以移植到“无论什么工作”。

+0

IIRC,'dlfcn.h'是POSIX(POSIX.1-2001)的一部分,所以它应该非常便携。即使是一些更新的Windows。 – peterph

+0

真正的问题是符合标准的C禁止在void *和函数指针之间进行投射;一个*一些*系统,如linux,可以工作,但在其他系统上它不会(BSD),您必须改用dlfcn。在这个问题上有大量的线程。 - 我只是想尽量减少#如果我必须使用这种方式。 – Doug

+0

但你不是在void和函数指针之间进行投射。你在一个void和一个结构指针之间进行投射。该结构包含一个函数指针。至少这就是你在示例代码中展示的内容。 – Art