C#調用C++DLL的方法,不同參數類型的調用方法
1. 參數爲基本類型,例如int, float, char等
[C++]
void fun(int value);
void fun(float vaue);
void fun(char ch);
[C#]
[DllImport("xxx.dll")]
public static extern void fun(Int32 value);
[DllImport("xxx.dll")]
public static extern void fun(float value);
[DllImport("xxx.dll")]
public static extern void fun(char ch);
2. 參數爲基本類型 + 指針, 例如int*, float*, char* 等
[C++]
void fun(int* value);
void fun(float* vaue);
void fun(char* ch);
[C#]
[DllImport("xxx.dll")]
public static extern void fun(ref Int32 value);
[DllImport("xxx.dll")]
public static extern void fun(ref float value);
參數爲char*,在C#中有幾種實現方式
A. public static extern void fun(string ch); //ch內容不會改變
B. public static extern void fun(StringBuilder ch); //ch內容會改變
3. 參數爲結構體
[C++]
struct point
{
int value; //基本類型
char ch; //基本類型
int number[100]; //數組
char buffer[100]; //字符串數組
};
void fun(point pt);
[C#]
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
4. 參數爲結構體指針
[C++]
void fun(point* pt);
[C#]
[DllImport("xxx.dll")]
public static extern void fun(ref point pt);
5. 參數爲結構體, 並且結構體還嵌套結構體
[C++]
struct point
{
int value; //基本類型
char ch; //基本類型
int number[100]; //數組
char buffer[100]; //字符串數組
struct point pt; //嵌套結構體
};
void fun(point pt);
[C#]
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
public point pt;
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
6. 參數爲結構體, 並且結構體還嵌套結構體指針或者雙指針
[C++]
struct point
{
int value; //基本類型
char ch; //基本類型
int number[100]; //數組
char buffer[100]; //字符串數組
struct point* p1; //嵌套結構體指針
struct point** p2; //嵌套結構體雙指針
};
void fun(point pt);
[C#]
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
public IntPtr p1; //使用IntPtr替代嵌套指針
public IntPtr p2; //使用IntPtr替代嵌套指針
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
由於嵌套指針的使用比較複雜,需要藉助一些手段才能夠確保正常調用DLL方法
[C#]
class Program
{
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
public IntPtr p1; //使用IntPtr替代嵌套指針
public IntPtr p2; //使用IntPtr替代嵌套指針
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
static void Main(string[] args)
{
point pt = new point();
pt.p1 = Marshal.AllocHGlobal(Marshal.Sizeof(typeof(point)));
pt.p2 = Marshal.AllocHGlobal((Marshal.SizeOf(typeof(point))) * 2);
try
{
pt.value = 1;
//實現給p1賦值
point ptt = new point();
ptt.value = 1;
Marshal.StructureToPtr(ptt, pt.p1, false);
//實現給p2賦值
//由於雙指針不能夠直接傳值,需要用到中間結構的數組指針
IntPtr[] ptr = new IntPtr[2];
ptr[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(point)));
ptr[1] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(point)));
try
{
Marshal.StructureToPtr(ptt, ptr[0], false);
Marshal.Copy(ptr, 0, pt.p2, 2);
fun(pt);
//測試返回的指針值是否正確
ptt = (point)Marshal.PtrToStructure(pt.p1, typeof(point));
Marshal.Copy(pt.p2, ptr, 0, 2);
ptt = (point)Marshal.PtrToStructure(ptr[0], typeof(point));
ptt = (point)Marshal.PtrToStructure(ptr[1], typeof(point));
}
catch(System.Exception e)
{
string str = e.Message;
}
finally
{
Marshal.FreeHGlobal(ptr[0]);
Marshal.FreeHGlobal(ptr[1]);
}
}
catch(System.Exception e)
{
string str = e.Message;
}
finally
{
Marshal.FreeHGlobal(pt.p1);
Marshal.FreeHGlobal(pt.p2);
}
}
}