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