我想调用Net6 C#库的一个函数。函数需要一个指向结构的指针。结构内部是一个变长数组。我不知道如何正确地封送这个数组。
下面的代码是演示该问题的测试代码。
这是C程序库的标题:
typedef struct SubTest
{
char *name;
int num1;
} SubTest;
typedef struct Test
{
char *name;
int num1;
float num2;
SubTest *testarray;
int testarraylen;
} Test;
void PrintTestStruct(Test *teststruct);
下面是PrintTestStruct的实现:
void PrintTestStruct(Test *teststruct)
{
printf("Name: %s \n", teststruct->name);
printf("Num1: %d \n", teststruct->num1);
printf("Num2: %f \n", teststruct->num2);
printf("Array content: \n");
for(int i=0; i < teststruct->testarraylen; i++)
{
printf("Array Name %d: %s \n", i,teststruct->testarray[i].name);
printf("Array Number %d: %d \n", i,teststruct->testarray[i].num1);
}
}
下面是C#中的定义:
[StructLayout(LayoutKind.Sequential)]
public struct Test
{
public string name;
public int num1;
public float num2;
public IntPtr testarray;
public int testarraylen;
}
[StructLayout(LayoutKind.Sequential)]
public struct SubTest
{
public string name;
public int num1;
}
[DllImport("cshared")]
private static extern void PrintTestStruct(ref Test teststruct);
这就是我所尝试的:
public static void Main(string[] args)
{
var data = new Test();
data.name = "Hello from C#";
data.num1 = 5;
data.num2 = 3.2f;
data.testarraylen = 2;
var field1 = new SubTest();
field1.name = "Testarray 1";
field1.num1 = 1;
var field2 = new SubTest();
field2.name = "Testarray 2";
field1.num1 = 2;
SubTest[] subarray = {field1, field2};
IntPtr mem = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(SubTest)) * data.testarraylen);
for (int ix = 0; ix < 2; ix++)
{
Marshal.StructureToPtr<SubTest>(subarray[ix], mem, false);
mem += Marshal.SizeOf(subarray[ix]);
}
data.testarray = mem;
PrintTestStruct(ref data);
}
不幸的是结果是垃圾,数组的数据没有正确打印。我遵循了我在stackoverflow上找到的所有建议,但无法得到任何更好的结果。
问题:
1.有办法解决这个问题吗?
1.由于我可以访问C库的源代码,是否有更好的方法在C#和C之间传输这些类型的可变长度数组?我是否可以以某种方式更改C库以使其更容易?
1条答案
按热度按时间wbgh16ku1#
问题是您已经更改了
mem
的地址,但没有还原它。因此,解决方案是将偏移地址添加到
men
,而不是在循环中更改。我能以某种方式改变C库使之更容易吗?
IMO这是最简单的。