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

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

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


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


(3)按下图进行勾选

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


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


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


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


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


注意:__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"导出的函数名,如图二。


图一


图二

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

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

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


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


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

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


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

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

阅读更多
版权声明:本文为【CSDN博主:松一160】原创文章,未经允许不得转载。 https://blog.csdn.net/songyi160/article/details/50754705
个人分类: DLL
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭