c#调⽤c++dll中的类⽅法总结
背景
原始代码是c#form调⽤c#的dll,现因为需要将代码搬迁到linux中,需要先将c#的dll转为c++dll,因为c#的form暂时不⽅便搬迁,需要先转后的c++dll,也就是需要c#调⽤c++dll,原来的c#调⽤c#dll的调⽤耦合度较⾼,有对类成员变量和类函数的调⽤,
现对调⽤过程进⾏总结,如果有不合适的地⽅,希望⼤家指正
总结
调⽤⽅法有两种,⼀种是创建c++ CLR项⽬,对c++代码进⾏封装,可以参考
另⼀种⽅法,c#直接调⽤c++dll,在调⽤时,c++dll可以直接导出全局接⼝,也可以导出类,我们例⼦中使⽤全局接⼝的⽅法,因为对dll的改动较⼩,⽅便维护
举例如下:
创建c++dll
/
/CTest.h
class CTest1
{
public:
CTest1() { a = 0; b = 0; };
CTest1(int x, int y);
int a;
int b;
public:
int Add(int x, int y);
};
extern "C" TESTDLL_API CTest1 * GetObj(int x, int y) { return new CTest1(x, y); };
extern "C" TESTDLL_API int Test1_Add(CTest1 * obj, int x, int y) { return obj->Add(x, y); };
//CTest.cpp
CTest1::CTest1(int x, int y)
{
a = x;
b = y;
}
int CTest1::Add(int x, int y)
{
return x + y;
};
c#代码
namespace WindowsFormsApp2
{
class Class1
{
[DllImport("Dll1.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr GetObj(int x, int y);
[DllImport("Dll1.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public extern static int Test1_Add(IntPtr obj, int x, int y);
private IntPtr obj;
public void SetObj()
{
obj = GetObj(5,6);
}
public int Test1Add()
{
obj = GetObj(5, 6);
return Test1_Add(obj, 5, 7);
}
}
}
c# 调⽤代码
Class1 mytest = new Class1();
int x = mytest.Test1Add();
例⼦有点low,但⼤概流程是这样
注意点
1 c++中返回的数据不能是栈空间的局部变量,否则返回值与设置的值会不⼀样
2 返回的数组在c#中需要转为,例⼦如下
[DllImport("Dll1.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr Test_RetArry(IntPtr obj, ref int len);
public int[] RetArry()
{
int len = 0;
IntPtr a = Test_RetArry(obj, ref len);
int[] managedArray = new int[len];
Marshal.Copy(a, managedArray, 0, len);
return managedArray;
}
开发过程中遇到的问题总结:
1 c#需要使⽤c++中的类,c++中的定义不变,可以定义⼀个类指针即可,在c#中使⽤IntPtr类型接收此类指针,类的其余⽅法或者变量可以将此类指针作为传⼊传⼊,在c++中调⽤对应的⽅法
2 c++中的数组类型,在c++接⼝中改为指针类型,c#中使⽤IntPtr接收,并转为指针即可,参上上⾯注意点中的内容
3 c++string类型,改为char*, c#中仍然使⽤string,不需要改变
[DllImport("SimulatorDll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
writeline方法属于类private extern static IntPtr Start(IntPtr pObj, IntPtr config);
public string Start(IntPtr config)
{
Console.WriteLine(computeSerObj);
Console.WriteLine("..................");
Console.WriteLine(config);
IntPtr pRet = Start(computeSerObj, config);
string strRet = Marshal.PtrToStringAnsi(pRet);
return strRet;
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。