在VS2013中创建一个Win32控制台项目,单击下一步,然后选择Dll。
生成的工程目录结构为:
在自动生成的文件中,dllmain.cpp作为定义DLL应用程序的入口点,它的作用跟exe文件有个main或者WinMain入口函数是一样的。可以在目标cpp文件(dllcxj.cpp)中编写自己要实现的函数。
在C#中新建一个类(Cppdll.cs),引用对应的dll:
[DllImport("D:\\ConsoleApplication1\\bin\\dllcxj.dll")]
public static extern string GetString();
注意:需要在程序声明中使用System.Runtime.InteropServices命名空间。
DllImport作为C#中对C++的DLL类的导入入口特征,只能放置在方法声明上,并通过static extern对extern “C”进行对应。在需要的地方调用.dll中的函数:直接使用类调用静态方法,如:string s = Cppdll.GetString();
extern "C" __declspec(dllexport) int__stdcall Add(int x, int y)
{
···
}
extern ”C”:
通常来说,C++编译器可能会改变函数和变量的名字,从而导致严重的链接程序问题。例如,假设使用C++编写一个DLL,当创建DLL时,Microsoft的编译器就会改变函数的名字。函数名将被设置一个前导下划线,再加上一个@符号的前缀,后随一个数字,表示作为参数传递给函数的字节数。例如,下面的函数是作为DLL的输出节中的_MyFunc@8输出的:
__declspec(dllexport)LONG __stdcallMyFunc(int a,int b);
如果用另一个供应商的工具创建了一个可执行模块,它将设法链接到一个名叫MyFunc的函数,该函数在Microsoft编译器已有的DLL中并不存在,因此链接将失败。使用extern “C”关键字可以使编译器按照C语言的方式编译DLL文件,即编译时不改变函数名。
__declspec(dllexport):
__declspec(dllexport)的目的是为了将对应的函数放入到DLL动态库中。在 32位编译器版本中,可以使用__declspec(dllexport) 关键字从DLL导出数、函数、类或类成员函数,__declspec(dllexport) 会将导出指令添加到对象文件中,因此不需要使用.def文件。若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。
__stdcall:表明被调用方清理堆栈。
using System.Runtime.InteropServices;
System.Runtime.InteropServices命名空间提供各种各样支持 COM interop 及平台调用服务的成员,使程序可以与非托管代码进行交互操作。
[DllImport("dllfilepath")]
代码中DllImport关键字作用是告诉编译器入口点在哪里,并将打包函数捆绑在这个类中。DllImportAttribute 属性包括:
Dllfilepath:Dllfilepath要求写为静态常量,因此不方便使用表达式表示dll的路径,而直接写Dll的绝对路径又不方便程序的移植。推荐直接写dll的名称加后缀名,如:"XX.dll"。DllImport会按照顺序自动去寻找的地方: 1、exe所在目录 2、System32目录 3、环境变量目录。所以只需要把引用的DLL 拷贝到上述任意一个目录下即可。 不用写.dll绝对路径。
EntryPoint="MessageBoxA"使用EntryPoint属性设置函数名
CharSet 指示用在入口点中的字符集,如:CharSet=CharSet.Ansi;
SetLastError 指示方法是否保留 Win32"上一错误",如:SetLastError=true;
ExactSpelling 指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配,如:ExactSpelling=false;
PreserveSig指示方法的签名应当被保留还是被转换,如:PreserveSig=true;
CallingConvention指示入口点的调用约定,如:CallingConvention=CallingConvention.Winapi;建议增加特性 CallingConvention=CallingConvention.Cdecl,不然可能会出现 “堆栈不对称”错误。必须在标记为”static”和”extern”的方法上指定”DllImport”属性,每一个方法前面都需要添加DllImport。