2009-10-02 55 views
4

我正在嘗試使用通過C++ DLL提供的功能的C#應用​​程序。我現在有點難以讓DLLImport定義正確運行。C#/ C++ interop - 需要幫助定義我的數據結構

這裏的方程的C++方面:

struct Result 
{ 
    FLOAT first; 
    FLOAT second; 
}; 

struct ResultData 
{ 
    UINT   uint1; 
    UINT   uint2; 
    Result   result; 
    Result*   pResults; 
}; 

#define DllImport __declspec(dllimport)  
extern "C" 
{ 
    DllImport HRESULT APIENTRY Process(const PCWSTR FileName, const PCWSTR logfileFileName, const PCWSTR DataFileName, ResultData** ppResults); 
    DllImport HRESULT APIENTRY Release(ResultData* pResults); 
} 

在C#的一面,這是我迄今所做的:

[StructLayout(LayoutKind.Sequential)] 
    public struct Result 
    { 
     public float first; 
     public float second; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct ResultData 
    { 
     public uint uint1; 
     public uint uint2; 
     public Result result; 
     public Result[] Results; 
    }  

     DllImport("MyDLL.dll")] 
     static extern uint Release(ResultData pResults); 

     [DllImport("MyDLL.dll")] 
     static extern uint Process(string FileName, string logfileFileName, string DataFileName, ref ResultData ppResults); 

這是做了正確的方法是什麼?我最關心的是ResultData結構的pResults成員。我不希望按值複製,因爲它將是大量的數據,我不想複製內存......我如何確保不會發生?

我感謝您的幫助。

回答

5

跳到我的最直接的問題是ResultData中的Results成員。本機類型是Result*,但您已將其翻譯爲數組。這可能會或可能不會工作(不能記住我的頭頂)。但是,它的工作方式是編組爲IntPtr類型。

[StructLayout(LayoutKind.Sequential)] 
public struct ResultData 
{ 
    public uint uint1; 
    public uint uint2; 
    public Result result; 
    public IntPtr RawResults; 
    public Result Results { get { return (Result)Marshal.PtrToStructure(RawResults,typeof(Result)); } 
} 

這是假定它是單個值。如果它超過一個值,則需要更復雜的編組。

此外,本機釋放方法需要ResultData*,但在受管理的簽名中有一個簡單的值ResultData類型。它需要有相同的間接程度。您可以通過將其設置爲ref來實現此目的。

DllImport("MyDLL.dll")] 
static extern uint Release(ref ResultData pResults); 
+0

哼,單個值==一個值,afaict。你錯過了'超過'的最後一句我假設 – 2009-10-02 16:52:12

+0

@Vinko,是正確的。它驚人地令人驚訝,直到有人指出明顯的不一致:) – JaredPar 2009-10-02 16:55:49

0

如果您可以將接口保留爲純C原始類型,則不必進行任何編組。這會爲你節省很多心痛。