繁体   English   中英

将包含未知大小的int数组的结构从c#传递到c并返回

[英]Passing a struct containing an int array of unknown size from c# to c and back

我开始努力解决这个问题。 我一直在寻找帮助,而我尝试过的一切似乎都没有用。 我显然做错了。

无论如何-我将ac#结构定义为:

public struct TestStruct
[StructLayout(LayoutKind.Sequential)]
{
   public int num;
   public IntPtr intArrayPtr;
}

在我的C#代码主体中,我有:

public class Testing
{
   [DllImport("testing.dll")]
   static extern void Dll_TestArray(out IntPtr intArrayPtr);

   public GetArray()
   {
      IntPtr structPtr = IntPtr.Zero;
      TestStruct testStruct;
      structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(testStruct));
      Marshal.StructureToPtr(testStruct, structPtr, false);

      Dll_TestArray(structPtr);

      testStruct = (TestStruct) Marshal.PtrToStructure(structPtr, typeof(TestStruct));
   }
}

因此,现在介绍c ++部分。 从结构开始:

struct TestStruct
{
   public:
     int  num;
     int* intArray;
}

现在的功能:

extern "C" __declspec(dllexport) void Dll_TestArray(TestStruct *&testStruct)
{
   int num = 15;
   testStruct->num = num;
   testStruct->intArray = new int[num];

   for (int i = 0; i < num; i++)
     testStruct->intArray[i] = i+1;  
}

所以-我遇到的问题是,当我将结构恢复为C#时,我的结构不是应该的样子。 我可以看到num字段已正确填写:显示为15。但是,仍然是IntPtr设置为零。 用c ++完成的数组创建尚未进行到c#中。

如果我尝试退后一步,然后再回到dll函数中,则可以看到该数组已创建成功,并且仍保留了该信息。

因此,未将结构中的c#intptr设置为在c ++中创建的指针(如果可以的话)。

所以我的问题确实是-如何使这项工作正常进行?

我希望能够从dll(一种包含所有我需要的信息)的结构中找回。 也就是说,在此示例中,元素的数量以及指向数组的指针。 这样,我就可以在intptr上执行Marshal.Copy以获得数组。

如果还有另一种方法可以做到,那么我将非常高兴。 我已经尝试了几种方法,但没有成功。 这包括尝试在c#中使用以下结构(该结构包含int数组,而不是intptr):

public struct TestStruct
{
   public int num;

   // i have tried various methods to marshal this- eg:
   // [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_I4]
   public int[] intArray;
}

而且我还尝试通过引用本身而不是intptr传递结构。 在此问题上的任何帮助将不胜感激。 我无法更改c ++代码,但是可以更改c#代码。

首先,将C ++代码更改为仅使用一个间接级别:

extern "C" __declspec(dllexport) void Dll_TestArray(TestStruct &testStruct)
{
     const int num = 15;
     testStruct.num = num;
     testStruct.intArray = new int[num];
     for (int i=0; i<num; i++)
         testStruct.intArray[i] = i+1;  
}

在C#方面,您需要这样做:

public struct TestStruct
{
    public int num;
    public IntPtr intArray;
}

[DllImport("testing.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void Dll_TestArray(out TestStruct testStruct);

public GetArray()
{
    TestStruct testStruct;
    Dll_TestArray(out testStruct);
    int[] arr = new int[testStruct.num];
    Marshal.Copy(testStruct.intArray, arr, 0, arr.Length);
    // need to call back to DLL to ask it to deallocate testStruct.intArray
}

您还需要导出一个函数,该函数将取消分配使用C ++堆分配的数组。 否则会泄漏它。

也许更简单的方法是更改​​设计,以使调用方分配缓冲区。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM