3

我有一个 C 程序,我在其中通过函数名称“动态”获取函数指针(即,我将函数名称作为字符串传递并获取指向函数的指针)。我已经在 Linux 中使用 dlopen 和 dlsym 做到了这一点,我想它也可以在任何其他类 Unix 中使用dlfcn

当我尝试使用 MinGW 将该程序移植到 Windows 时,问题就开始了。当我尝试使用“GetProcAddress(handle, symbol_name)”查找名称时,其中“symbol_name”是我的回调函数的名称,“handle”是“GetModuleHandle(NULL)”返回的当前可执行文件的句柄,我什么也没得到因为 MinGW 名称修饰在我的符号名称中添加了一个“_”。

显而易见的解决方案(在我想要的符号前加上“_”)对于可移植性似乎有点“危险”(编译器可以为其中一些添加两个下划线吗?我不知道),所以,我问:

  • 有更好的方法来防止编译器对我的符号进行名称修改吗?(或其中的一个子集,只有我需要动态查找的回调);

  • 或者一种让 GetProcAddress 即使在损坏时也能找到它们的方法?

我还尝试了选项-fno-leading-underscore,但它也删除了所有外部符号的修饰,使程序无法与 stdlib 等链接(另外,文档上的警告有点吓人)。

另外,请注意我使用的是纯 C——我的代码的任何部分都没有 C++——我所有的代码都存在于一个“.exe”中。

TIA

4

2 回答 2

0

不确定您的问题是什么,因为我无法使用我能想到的最简单的 DLL 示例来重现它:

/* hello_dll.c */
#include <stdio.h>

__declspec(dllexport) void hello ( void )
{
    puts ( "Hello, DLL!");
}

/* hello_exe.c */
#include <windows.h>
#include <stdio.h>  

int main () {
    typedef void (*pfunc)(void);

    HANDLE hself;

    pfunc hello;

    hself = GetModuleHandle(NULL);

    hello = (pfunc)GetProcAddress(hdll, "hello");

    hello();

    return 0;
}

这是使用没有特殊标志的 MinGW gcc 的命令行,一切正常:

gcc src\hello_dll.c src\hello_exe.c -o bin\hello.exe
$ bin\hello.exe
Hello, DLL!
$ gcc --version
gcc (GCC) 4.5.0

__declspec(dllexport)如果您从自己那里获得功能,它就无法工作;使用它创建 DLL 时gcc -shared似乎没有必要,但如果从 exe 导出函数则似乎是必需的。

于 2011-02-12T18:36:01.970 回答
0

C 不使用名称修饰。特别是,它不会向名称添加任何类型信息(与 C++ 不同)。但是有些平台对名称进行了小修改,例如在下划线前加前缀。与 C++ 不同的是,它只是特定于平台的,而不是特定于编译器的。

到目前为止,在我见过的所有平台上,我只看到没有修改或前导下划线。

所以我建议你使用一些ifdef来推导当前平台是否使用下划线。

(Windows 对某些 Windows API 函数进行了另一项小修改,以区分 ANSI 和 Unicode 版本。但这可能与您的情况无关。)

也许其他人可以指出不同平台上 C ABI 的一些官方文档。

于 2011-02-12T18:36:41.287 回答