在VS中用C++编写可被其它语言调用的动态库DLL

2 篇文章 0 订阅

VS200+用C++创建动态库DLL步骤如下:

(1)启动VS2015》文件》新建》项目,按下图进行选择填写,选择Win32控制台应用程序或Win32项目都可以,这两相都会弹出相同的创建窗口,如第二张图,第三张图。

https://img-blog.csdn.net/20160227124429884?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

(2)在Win32应用程序向导对话框中选择【下一步】

https://img-blog.csdn.net/20160227124531931?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

(3)按下图进行勾选

https://img-blog.csdn.net/20160227124656166?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

预编译头作用:VS 默认情况下会创建并使用预编译头文件(也就是自动创建 StdAfx.h 和 StdAfx.cpp 这两个文件),以便在编译时加快编译速度,预编译器将它编译后,会生成一个 Pre-compiled header ,也就是 pch 文件,这样下次就可以直接使用这里已经编译好了的代码了。

(4)整个测试项目创建后,整体效果如下图:

https://img-blog.csdn.net/20160227125553294?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

(5)在解决方案中找到【头文件】然后右击选择【添加】》【新建项】,在弹出的添加新项对话框中进行如下选择:

https://img-blog.csdn.net/20160227130101249?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

(6)打开DLLTest.cpp并添加如下图红色框中的函数test1和test2,同时将DLLTest.h头文件包含进来,具体如下图:

https://img-blog.csdn.net/20160227130447269?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

(7)打开DLLTest.h并添加函数test1和test2的导出形式,具体如下图:

https://img-blog.csdn.net/20160227130646880?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

注意:__stdcall定义导出函数入口点调用约定为_stdcall

     extern "C"说明导出函数使用C编译器,则函数名遵循C编译器的函数名修饰规则,不加extern "C"说明使用C++编译器的函数名修饰规则,两种规则区别如下:

   (1)C编译器的函数名修饰规则 

     对于__stdcall调用约定,编译器和链接器会在输出函数名前加上一个下划线前缀,函数名后面加上一个“@”符号和其参数的字节数,例如 _functionname@number。__cdecl调用约定仅在输出函数名前加上一个下划线前缀,例如_functionname。__fastcall调用约定在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,例如@functionname@number

    (2)C++编译器的函数名修饰规则

     C++的函数名修饰规则有些复杂,但是信息更充分,通过分析修饰名不仅能够知道函数的调用方式,返回值类型,甚至参数个数、参数类型。不管__cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”开始,后面紧跟函数的名字,再后面是参数表的开始标识和按照参数类型代号拼出的参数表。对于__stdcall方式,参数表的开始标识是“@@YG”,对于__cdecl方式则是“@@YA”,对于 __fastcall方式则是“@@YI”。参数的具体含义见上篇博客【VS2015用C++创建的动态库导出函数名乱码原因分析】。

(8)使用extern "C"导出的函数名,如图一,不使用extern "C"导出的函数名,如图二。

https://img-blog.csdn.net/20160227134710376?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

图一

https://img-blog.csdn.net/20160227135002549?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

图二

注意在图二中如果看到的函数不是图中所示,请在函数名上右击去掉对【Undecorate C++ Functions】的选择

(9)针对上面的叙述可以看出无论是添加extern "C"还是不添加,都不是我们想要的函数名,.h头文件的作用仅仅能导出动态库、明确编译链接方式及确定入口点约定,还一个重要作用是打包给开发者,使其了解动态库导出的函数及对应的的参数,为了确保导出函数名及入口点函数不变,此时需添加.def文件,步骤如下:

(10)在解决方案中找到【源文件】右击选择【添加】》【新建项】,在弹出的添加新项对话框中进行如下图所示选择:

https://img-blog.csdn.net/20160227135753369?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

(11)在DLLTest.def文件中写入如下代码:

https://img-blog.csdn.net/20160227135915365?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

使用def文件的意义:将编译器生成的函数修饰去掉,用更加自然、更加容易理解、更加容易记忆的名字来命名函数,而不是一串人一看就吓一跳的                                             修饰名字。

(12)在生成解决方案前先进行如下修改,CPU选X86还是X64随便你啦

https://img-blog.csdn.net/20160227140443867?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

13)请注意一定要是Release模式而不能是Debug模式,否则生成的动态库DLL文件有可能还是不能被其他语言调用,原因现在还不清楚,有知道的朋友请留言,谢谢。为对比可查看Release文件夹和Debug文件夹中生成的动态库DLL文件的大小也是不同的。

14)用def文件导出的动态库DLL既可以保证函数名不变也可以保证动态库DLL的入口点函数名不变,同时在.cpp文件中函数定义中加入__stdcall就可以实现导出的DLL被其它语言调用,此时.h头文件的作用仅仅打包给开发者,供其查看导出的函数名及相应参数而已。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值