使用extern c和dllexport vs模块定义的stdcall名称修改(msvc ++)

min*_*ina 15 c++ name-mangling stdcall dllexport visual-c++

我试图导出一个简单的测试函数,用于处理一个应用程序(fyi:mIRC),它将调用约定指定为:

int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
Run Code Online (Sandbox Code Playgroud)

现在,要从应用程序中调用它,我将使用test_func,但我注意到由于名称错误,它并不像我想象的那么简单.

通过类似的主题,我已经了解到将extern"C"__declspec(dllexport)结合使用是一种等效的(某种程度上)方法,可以将重整数据删除到模块定义(.def).但是,当使用extern/dllexport方法时,我的函数(作为示例)始终是_test_func @ numbers,而.def删除了所有需要导出到的应用程序所需的修改.

有人可以解释一下这是为什么吗?我只是对这两种方法感到好奇.谢谢!

Mar*_*wis 14

extern "C"与stdcall无关:它只声明C++名称修改(也称为类型安全链接;在符号名称中包含类型信息)是禁用的.无论是使用C调用约定还是使用stdcall调用约定,都需要使用它.

在stdcall调用约定中,被调用者从堆栈中删除参数.为了安全起见,导出的名称包含被调用者将从堆栈中删除的字节数.

如果要导出的应用程序要求不@number向名称添加后缀,则可能意味着它需要C调用约定.所以你应该停止声明函数为__stdcall.当你声明它时declspec(dllexport),你应该在DLL中获得一个未修饰的名称.

在DEF文件中,您可以随意调用该函数; 没有进行额外的检查.

  • windows api函数是stdcall但没有@number,在Windows上标准做法就是这样做. (18认同)

Pup*_*ppy 12

dllexport/import设计为自己加载,而不是使用GetProcAddress的旧C库.您看到的错误是所有Microsoft编译器长期为__stdcall函数所做的事情.最有可能的是,您的目标要么需要__cdecl函数,要么不要__stdcall,但如果没有,则需要使用.def文件来专门取消名称.