前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DLL 导出符号的两种方式

DLL 导出符号的两种方式

作者头像
Harper
发布2021-07-27 10:16:22
1.4K0
发布2021-07-27 10:16:22
举报
文章被收录于专栏:Harper的碎碎念

最近恰好需要用 C++ 实现一个供 C# .NET 调用的模块,用dllexport导出符号的时候出现了一点问题,明明已经看到了导出符号,但是 .NET 在调用的时候,就是找不到方法。然后用 def 文件的方式导出符号就正常,突然对这两种方式的区别产生兴趣,之前一直没有研究过,就仔细了查阅一番。

以导出名为 TESTFUNC 方法为例:

def 文件方式

,正常在程序中定义方法,然后新建一个 .def 文件,内容类似

代码语言:javascript
复制
LIBRARY
EXPORT
    TESTFUNC

在其他工程使用这个方法的时候需要头文件,然后在连接时指定 .def 文件目录。

dllexport方式

在定义 TESTFUNC 方法时,在声明前加上 __declspec(dllexport)

区别

这里就不得不说导出符号在 DLL 中的形式。实际上对于 C++ 来说,当导出的时候,不会以原名导出,因为会加上一些符号字母后缀,实际上如果了解 C++ 的人,也会知道 C++ 在处理函数重载的时候,其实也用了这个套路,实际上编译之后就没有重载的概念了,而是根据参数生成了独一无二的方法名。

那说回来既然名字不同,那为什么其他模块调用还没问题呢。回答这个问题之前要先知道其他模块如何引用。

调用导出函数的方式

一般有三种形式:

  • .h 提供声明之后,直接调用,在连接的时候指定 .def 文件目录;
  • .h 提供声明之后,直接调用,链接的时候指定 .lib 文件地址
  • 内部声明要调用函数的函数指针,loadlibrary 之后,直接取到函数地址,调用函数;

了解了这三种方式之后,就可以回答上边的问题。

  • 对于1、2两种方式,由编译器自动转换函数名,寻找到正确的地址,链接之;
  • 对于第3种方式,如果不把真正的函数方法名写对,就找不到函数了。

所以其他模块调用没问题。

话说回来,那也不可能每次都把@那些符号写对。所以会看到有时候导出的时候_extern "C" _declspec(dllexport)这样写,这是为了让函数以 C 的方式来编译,这样导出的方法就是没有那些符号的了,但这样有个问题,就是函数必须以 C 方式调用,而且也不能用来导出类对象,原因是显而易见的……

其实当了解上边之后,不难发现,1、2才是我们最想要的,3就很局限。这样问题就来了,1、2两种方式又有什么区别呢:

区别就在这个 .lib 上,如果在 C++ 或者 C 工程这个范围来说,确实没区别。但是假如调用工程不是 C++ 工程呢,他就是个 C# 工程呢,他是没办法用 .lib 的。

综上所述:.def 文件的方式才是最通用的做法。那回到我最初的问题,我的 C# 工程之所以在调用使用 dllexport导出的方法失败,就是因为,我没有写对真正的方法名(带一堆符号的那个)。而使用 .def 文件的话,就没有这个问题了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • def 文件方式
  • dllexport方式
  • 区别
    • 调用导出函数的方式
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档