C# 调用 C 写的 dll,历经千辛,缘于疏忽

jmcooler jmcooler 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
问题我已经解决了,写出来,只是望各位参照,以后多个小心。无用你们回答,但请你们顶贴,呵呵

用 VS 2010 写了一个 C 的 win32 dll,就连最简单的函数 void Func(),都无法在另外一个 C# 工程里被调用,总是提示"无法找到这个函数的入口"。有这么蹊跷么,办法用尽,还是调不了。

首先,怀疑是函数名 Copy 错了,再次几个调用约定都试过了。在网上找了一大堆资料,包括 C# 调用C 注意事项,微软官方的例子,整个比对下来,没发现我的代码有任何问题。
于是开始怀疑 VS 2010 建的 C 动态库,有自身的 Bug。
可是整个动态库,无论用什么查看软件,都能清楚地看见输出函数的列表。

网上一些人的 dll 中,总是有 extern "C" __declspec(dllexport) void Func(),这引起了我的注意,我也原样照搬。然而编译时 VS 提示我,extern "C" 是古老的用法,我不得不又去掉 extern "C" 字样。问题仍然如初。
我差点想下载一个 VC6 来建立和编译我的 dll,不过,随着折腾越多,有些不经意的发现起了作用

我发现,我建的 win32 动态库,默认添加了输出宏:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
头文件中的函数声明和.c 文件中的函数体,都加了 DLL_API 来输出函数:
MYDLL_API void Func();
MYDLL_API void Func() { }
显然,就是没有 extern "C" 字样。

首先干掉输出宏,并干掉头文件中的函数声明,直接将函数体写为 __declspec(dllexport) void Func() { },然而还是不行
真是不可思议,黔驴技穷了。
偶然间想起来,刚刚 extern "C" __declspec(dllexport) void Func() { } 在函数体前面加了 extern "C",但函数声明里,还是用的输出宏,换句话说,函数体是 extern "C" __declspec(dllexport) void Func() { },但头文件里的声明仍旧是 __declspec(dllexport) void Func();
这种不一致,导致 VS 提示 extern "C" 是古老的用法,误导了我,我还以为 VS2010 真就不支持 extern "C" 了呢。

当将函数体写为 extern "C" __declspec(dllexport) void Func() { } 之后,这次,报的错是,调用约定不一致,加上 CallingConvention = CallingConvention.Cdecl 之后,即成功了。

一切都是因为 VS2010 的 Bug 和误导,才让我折腾了一整天。
结论就是:VS2010 建立的 win32 动态库,按照默认输出宏,虽然编出的 DLL 完全正确,但 C# 就是不认识。
唯有仅写函数体为:
extern "C" __declspec(dllexport) void Func()
{
}
方可被 C# 识别,你说 VS 的过错有多大。

...全文
评论 9
收藏 已收藏
分享
返回顶部
jmcooler
C# 111,128 成员 642,536 内容