将指向结构数组指针的指针从C#传递给C ++

时间:2016-03-18 20:34:10

标签: c# c++ pinvoke marshalling unmanaged

我想将指针传递给从C#到C ++的结构数组的指针。使用以下代码我只获得c ++中的第一个元素,不传递数组的第二个和第三个元素。为什么?此外,尝试使用StructureToPtr但没有帮助。我做错了什么?

C ++代码

 struct structure 
{
   short ps;

};
   __declspec(dllexport)short Testmethod(structure** aa)
    {
     if (aa!= 0 && aa[0]->ps == 26 && aa[1]->ps == 27)
     {          
        return 1;
      }    
      return  0;
    }

C#代码

[DllImport("Wrapper.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern short Testmethod(ref IntPtr a);

     [StructLayout(LayoutKind.Sequential)]           
     public struct SampleStructure
    {
       public short ps;

    };

 SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
                        GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);
                        IntPtr ptr = gch.AddrOfPinnedObject();
                        ret = Testmethod(ref ptr);

我无法更改c ++代码,我无法访问它。如果将c ++代码更改为以下方式之一,则可以正常工作。如何在不更改c ++代码的情况下完成它? 的更新

如果我更改c ++代码,

方式1:有效。但我不能改变C ++代码。这不是我的代码。

C ++代码

__declspec(dllexport)short Testmethod(structure* aa)

C#代码

            fixed (SampleStructure* pArray = dataInformation)
            {
                ret = Testmethod(pArray);
            }
如果我更改c ++代码,

方式2:有效。但我不能改变C ++代码。这不是我的代码。

C ++代码

__declspec(dllexport)short Testmethod(structure Getcsharpval[], int size)

c#c​​ode

 public unsafe static extern short Testmethod([MarshalAs(UnmanagedType.LPArray,SizeParamIndex=3)] SampleStructure[] array);
 SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
 ret = Testmethod( data);

3 个答案:

答案 0 :(得分:0)

我认为你的c函数有错误的原型。 试试:

_declspec(dllexport)short Testmethod(structure* aa)
{

    if (aa != 0
       && aa[0].ps == 26 && aa[1].ps == 27)

    {
        return 1;
    }

    return 0;
}

在c#示例中,您有一个struct数组。该数组是一个引用类型,您需要固定内存。数组是struct的内存中的一个序列,它是值类型(并且不需要pin)。所以在数组中你没有指针而是直接结构。

答案 1 :(得分:0)

您需要将IntPtr[]传递给C ++代码。

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern short Testmethod(IntPtr[] aa)

分配IntPtr[]数组并填充它。通过固定每个结构并使用固定对象的地址来实现。或者使用Marshal.StructureToPtr执行此操作。如果使用后者,则必须在调用后释放非托管内存。

答案 2 :(得分:0)

好的,我通过使用以下代码创建指向结构指针的指针来解决。

    [DllImport("Wrapper.dll", CallingConvention = CallingConvention.StdCall)]
    public unsafe static extern short Testmethod (SampleStructure** passstructurepointer);

     unsafe
            {
                fixed(SampleStructure** p2p = new SampleStructure*[3])
                {
                    for (short i = 0; i < 3; i++)
                    {
                        var a = stackalloc SampleStructure[1];
                        a->ps = i;
                        p2p[i] = a;
                    }
                    var s= Testmethod(p2p);
                }
            }