CSharp如何調用dll中帶指針參數

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)}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章