2016-03-18 153 views
1

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

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 + +代码? 更新:

方法1:作品,如果我改变C++代码。但我无法更改C++代码。这不是我的代码。

C++代码

__declspec(dllexport)short Testmethod(structure* aa) 

C#代码

  fixed (SampleStructure* pArray = dataInformation) 
      { 
       ret = Testmethod(pArray); 
      } 

方式2:作品,如果我改变C++代码。但我无法更改C++代码。这不是我的代码。

C++代码

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

C#代码

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); 
+0

我没有太多的写作方法适合pinvoke的经验,但是,你是否尝试过将C++方法的签名更改为'short Testmethod(structure * aa)'?编辑:另外,既然你传递了一个指针,你应该也可以传递数据的长度。 – willaien

+0

你可以在你的项目中使用C++/Cli吗? – alangab

回答

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); 
       } 
      } 
+0

不需要不安全或堆栈分配 –

0

我觉得你的C函数有错原。 Try:

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

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

    { 
     return 1; 
    } 

    return 0; 
} 

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

+0

我无法更改C++代码,我无法访问它。如果更改C++代码,它的工作原理。我怎样才能不改变c + +代码?请参阅更新后的问题 –

0

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

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

分配一个IntPtr[]数组并填充它。通过固定每个结构并使用固定对象的地址来这样做。或者用Marshal.StructureToPtr这样做。如果使用后者,则必须在调用后取消分配非托管内存。