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++代碼進行封裝,可以參考

https://www.cnblogs.com/jshchg/p/12898853.html

另一種方法,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,但大概流程是這樣

 https://www.cnblogs.com/djh5520/p/14340517.html

注意點

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)]
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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM