c#与c++接⼝间调⽤时传递结构体 复杂结构体的传递
1. 输出参数,结构体作为指针传出
⾮托管部分代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31typedef struct
{
char name[20];
int age;
double scores[32];
}Student;
//Class中包含结构体数组类型
typedef struct
{
int number;
Student stedents[50];
}Class;
JNAAPI int GetClass(Class *pClass,int len)
{
for(int i = 0; i < len; i++)
{
pClass[i].number = i;
for(int j = 0; j< 50; j++)
{
/
/把name中的前20个字节⽤0代替
memset(pClass[i].stedents[j].name, 0, 20);
//给每个同学命名
sprintf(pClass[i].stedents[j].name, "name_%d_%d", i, j); pClass[i].stedents[j].age = j % 2 == 0 ? 15:20;
}//for
}//for
return0;
}
上⾯DLL 的导出函数要求传递的参数为它⾃定义的Class结构体数组, 那么我们在C#调⽤它时也要⾃定义对应的结构体了,我们可以定义为如下:
1 2 3 4
5 6 7 8 9[StructLayout(LayoutKind.Sequential)]
struct Student
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string name;
public int age;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public double[] scores;
}
[StructLayout(LayoutKind.Sequential)]
9 10 11 12 13 14 15 16 17[StructLayout(LayoutKind.Sequential)]
struct Class
{
public int number;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public Student[] students;
}
需要注意的是,这2个结构体中的数组⼤⼩⼀定要跟C++中的限定⼀样⼤⼩哦,接下来如何使⽤这个API来正确的获取数据呢,⼤多数⼈可能想到像这样的处理⽅式:
1 2 3 4Class myclass = new Class();
IntPtr ptr=Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Class))); GetClass(ptr);
Marshal.FreeHGlobal(ptr);
没错,这样的处理是没问题的,但是我们的API的参数是Class数组,这种处理⽅式只是传递⼀个Class结构体参数,所以这种⽅式在这⾥就不太合适了,!
那⼤家就想到先Class[] myclass = new Class[MaxClass]; 然后在⽤Marshal.AllocHGlobal 来获取myclass 数据的指针,
其实这样也是错的, 因为 Class结构中包含了,不能直接封送的Student结构,所以⽆论如何上⾯的想法是错误的!
那要怎么办呢,其实很简单,就是先分配⼀段⾮托管内存,并调⽤API后,再将⾮托管内容数据读取到托管结构体数据中!
结构体数组不能作为参数传递给函数⽰例演⽰代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15// 接⼝定义
[DllImport("CSharpInvokeCpp_CppDemo.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int GetClass(IntPtr pv, int len);
//复杂结构体传递测试代码
int size = Marshal.SizeOf(typeof(Class)) * 50;
IntPtr pBuff = Marshal.AllocHGlobal(size);
CppDLL.GetClass(pBuff, 50);
Class[] pClass = new Class[50];
for(int i = 0; i < 50; i++)
{
IntPtr pr = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(Class)) * i);
pClass[i] = (Class)Marshal.PtrToStructure(pr, typeof(Class));
}
Marshal.FreeHGlobal(pBuff);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论