2016-03-18 150 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這樣做。如果使用後者,則必須在調用後取消分配非託管內存。