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