C#调用C++比较常见的两种方式,一种是调用C++dll提供的接口,另一种直接调用C++提供的类,使用上更灵活一些。
其他的方式我也不知道了。
这里暂时只讲第一种方式,这种方式用得比较多。
目录
传入参数
传入数值类型的参数
这个就比较直接了,没什么变化,接口是int型,调用处也是int型,这种大家都有的类型传递起来就比较方便。
举个最简单的例子:
.h文件中
extern "C" __declspec(dllexport) bool setInt(int a);
.cpp文件中:
bool setInt(int a)
{
cout << a << endl;
return true;
}
.cs文件中:
[DllImport("MyDll.dll")]
static extern bool setInt(int a);
int a = 1;
setInt(a);
传入字符串类型的参数
c++中使用char*
参数类型,在C#中可以选择使用string
或者StringBuilder
。
接口声明:
extern "C" __declspec(dllexport) bool setString(char* a);
定义:
bool setString(char* a)
{
cout << a << endl;
return true;
}
调用处:
[DllImport("MyDll.dll")]
static extern bool setString(StringBuilder a);
[DllImport("MyDll.dll")]
static extern bool setString(string a);
string b = "ceshi";
setString(b);
StringBuilder sb = new StringBuilder("shiyixia");
setString(sb);
传入结构体类型的参数
结构体的传递需要使用指针,接口处可以定义为void*
类型的参数,也可以使用结构体指针,C#处传递参用IntPtr
类型,传指针都是用这个类型就可以了。
结构体定义:
typedef struct __RESULT_STRUCT__
{
char name[256]; // 这边注意长度要和接口调用处统一起来
int x;
int y;
int width;
int height;
double confidence;
} RESULT_STRUCT, *P_RESULT_STRUCT;
接口声明:
extern "C" __declspec(dllexport) bool setStruct(P_RESULT_STRUCT d1);
定义:
bool setStruct(P_RESULT_STRUCT d)
{
cout << d->name << endl;
cout << d->x << endl;
cout << d->y << endl;
cout << d->width << endl;
cout << d->height << endl;
cout << d->confidence << endl;
return false;
}
调用处:
[StructLayout(LayoutKind.Sequential)]
private struct Result
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string name;
public int x;
public int y;
public int width;
public int height;
public double confidence;
}
[DllImport("MyDll.dll")]
static extern bool setStruct(IntPtr result);
Result d = new Result
{
name = "测试一下name",
x = 101,
y = 102,
width = 103,
height = 104,
confidence = 0.55
};
IntPtr dPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Result)));
Marshal.StructureToPtr(d, dPtr, false);
setStruct(dPtr);
Marshal.FreeHGlobal(dPtr);
传入数组类型的参数
传入元素为数值型的数组
数组的传递需要使用指针,接口处都可以定义为void*
类型的参数,也可以定义为具体的类型的指针,C#处传递参数用IntPtr
类型。
以int
型数组举例,其他都是差不多的:
接口声明:
extern "C" __declspec(dllexport) bool getArray(void* data, int len);
定义:
bool getArray(void* data, int len)
{
int* d = (int*)data;
for (int i = 0; i < len; i++)
{
cout << d[i] << endl;
}
return true;
}
调用处:
int[] c = new int[] { 1, 2, 3, 4 };
IntPtr cPtr = Marshal.AllocHGlobal(sizeof(int) * c.Length);
Marshal.Copy(c, 0, cPtr, c.Length);
getArray(cPtr, c.Length);
Marshal.FreeHGlobal(cPtr);
[DllImport("MyDll.dll")]
static extern bool getArray(IntPtr data, int len);
传入结构体数组
和传入单个的结构体也差不多,就是把结构体一个个按顺序排排好。
接口声明:
extern "C" __declspec(dllexport) bool setStructArray(P_RESULT_STRUCT d2, int len);
定义:
bool setStructArray(P_RESULT_STRUCT d2, int len)
{
for (int i = 0; i < len; i++)
{
RESULT_STRUCT s = d2[i];
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
cout << s.name << endl;
cout << s.x << endl;
cout << s.y << endl;
cout << s.width << endl;
cout << s.height << endl;
cout << s.confidence << endl;
cout << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl;
}
return true;
}
调用处:
Result e = new Result
{
name = "测试两下name",
x = 201,
y = 202,
width = 203,
height = 204,
confidence = 0.66
};
Result[] f = new Result[] { d, e };
IntPtr g = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Result)) * f.Length);
Marshal.StructureToPtr(f[0], g, false);
Marshal.StructureToPtr(f[1], g + Marshal.SizeOf(typeof(Result)), false);
setStructArray(g, f.Length);
Marshal.FreeHGlobal(g);
[DllImport("MyDll.dll")]
static extern bool setStructArray(IntPtr result, int len);
传出参数
传出数值型的参数
接口定义处参数类型加&
,调用处用ref
。
接口声明:
extern "C" __declspec(dllexport) bool getInt(int& a);
定义:
bool getInt(int& a)
{
a = 202;
return true;
}
调用:
int h = 0;
getInt(ref h);
Console.WriteLine(h);
[DllImport("MyDll.dll")]
static extern bool getInt(ref int a);
传出字符串类型的参数
参数使用char*
,调用处使用StringBuilder
。
接口声明:
extern "C" __declspec(dllexport) bool getString(char* a);
定义:
bool getString(char* a)
{
string b = "ceshi测试";
strcpy_s(a, b.length() + 1, b.c_str());
return true;
}
调用:
[DllImport("MyDll.dll")]
static extern bool getString(StringBuilder sb);
StringBuilder i = new StringBuilder(1024);
getString(i);
Console.WriteLine(i);
传出结构体类型的参数
接口声明:
extern "C" __declspec(dllexport) bool getStruct(P_RESULT_STRUCT data);
定义:
bool getStruct(P_RESULT_STRUCT data)
{
char a[123] = "这是新的结构体";
strcpy_s(data->name, a);
data->x = 122;
data->y = 123;
data->width = 124;
data->height = 125;
data->confidence = 0.98;
return true;
}
调用:
[DllImport("MyDll.dll")]
static extern bool getStruct(IntPtr result);
IntPtr k = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Result)));
getStruct(k);
Result l = (Result)Marshal.PtrToStructure(k, typeof(Result));
Console.WriteLine("{0},{1},{2},{3},{4},{5}", l.name, l.x, l.y, l.width, l.height, l.confidence);
传出数组类型的参数
传出数值型数组
接口声明:
extern "C" __declspec(dllexport) bool getIntArray(int* data, int& len);
定义:
bool getIntArray(int* data, int& len)
{
len = 10;
for (int i = 0; i < len; i++)
{
data[i] = i;
}
return true;
}
调用:
[DllImport("MyDll.dll")]
static extern bool getIntArray(IntPtr data, ref int len);
IntPtr m = Marshal.AllocHGlobal(sizeof(int) * 100);
int n = 0;
getIntArray(m, ref n);
int[] p = new int[n];
Marshal.Copy(m, p, 0, n);
for (int o = 0; o < n; o++)
Console.WriteLine(p[o]);
传出字符串型数组
未完待续
传出结构体型数组
未完待续