C# 调用C++ dl注意事项

    最近经常在C#代码调用C++的dll文件,对于遇到的坑总结一下

1、针对C++的dll文件常见的几种约定方式

__stdcal:参数从右向左的顺序进行入栈,堆栈由被调用方进行释放,即C++的dll的函数进行堆栈自行管理

__cdecl:参数从右向左的顺序进行入栈,堆栈由调用方维护,即谁调用,是负责堆栈释放

C++的默认调用约定为__cdecl,我们在编写C#时,需要注意调用函数约定方式。

2、再C#代码中,默认的调用方式为__stdcall的约定的方式,如果无相关参数传递,则无论是否表明调用约定,均不会报错

extern "C" void __declspec(dllexport)   TestWay(LPSTR lpPara)
{
	cout<<"调用了TestWay 传递参数"<

 当你调用TestWay,程序会报错,当你加上CallingConvention = CallingConvention.Cdecl时,则可以调用成功!

3、CharSet.Ansi:以多字节字符串的形式封送字符串

     CharSet.Unicode:以 Unicode 2 字节字符形式封送字符串

    CharSet.Auto: 

//     针对目标操作系统适当地自动封送字符串。在 Windows NT、Windows 2000、Windows XP 和 Windows Server
        //     2003 系列上,默认值为 System.Runtime.InteropServices.CharSet.Unicode;在 Windows 98
        //     和 Windows Me 上,默认值为 System.Runtime.InteropServices.CharSet.Ansi。尽管公共语言运行时默认值为
        //     System.Runtime.InteropServices.CharSet.Auto,但使用语言可重写此默认值。例如,默认情况下,C# 将所有方法和类型都标记为
        //     System.Runtime.InteropServices.CharSet.Ansi。

编写调用C++代码时,主要编码格式,否则会有意想不到的错误

以上C++ Dll代码再多字节编码编写

修改代码

[DllImport("TestDll.dll",CallingConvention = CallingConvention.Cdecl,CharSet = CharSet.Auto)]
public extern static void TestWay(string lpPara);

再次调用是则会运行结果:

分析原因就是传递的编码格式导致这种C++char* 指针错误

4、关于传递int* 参数读取方式

extern "C" void __declspec(dllexport)  TestIntVar(int *pIntValue)
{
	*pIntValue = 10;
	cout<<"调用了TestIntVar传递参数int = "<<*pIntValue<

同样也可以使用out,ref的方式获取

[DllImport("TestDll.dll",CallingConvention = CallingConvention.Cdecl)]
public extern static void TestIntVar(out int ptr);

[DllImport("TestDll.dll",CallingConvention = CallingConvention.Cdecl)]
public extern static void TestIntVar(ref int ptr);

 

你可能感兴趣的:(C#调用C++相关代码)