2013-08-29 69 views
7

注意:最終的工作解決方案是在編輯之後!將結構從非託管C++傳遞到C#

我希望有人能幫我解決我過去幾天一直試圖解決的問題。

我想從一個非託管的C++ DLL傳遞一個結構到一個C#腳本。這是我到目前爲止有:

C++

EXPORT_API uchar *detectMarkers(...) { 
    struct markerStruct { 
      int id; 
    } MarkerInfo; 

    uchar *bytePtr = (uchar*) &MarkerInfo; 

    ... 

    MarkerInfo.id = 3; 
    return bytePtr; 
} 

C#

[DllImport ("UnmanagedDll")] 
    public static extern byte[] detectMarkers(...); 

... 

[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)] 
public struct markerStruct 
{ 
    [MarshalAs(UnmanagedType.U4)] 
    [FieldOffset(0)] 
    public int Id; 
} 

... 

markerStruct ByteArrayToNewStuff(byte[] bytes){ 
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
    markerStruct stuff = (markerStruct)Marshal.PtrToStructure(
     handle.AddrOfPinnedObject(), typeof(markerStruct)); 
    handle.Free(); 
    return stuff; 
} 

... 

print(ByteArrayToNewStuff (detectMarkers(d, W, H, d.Length)).Id); 

的問題是,這個工作,但打印的值是完全關閉(有時它打印約400,有時最大int值)。

我在猜測,我在C#中編組結構時出了問題。有任何想法嗎?

編輯:

這是工作溶液使用參考:

C++

struct markerStruct { 
    int id; 
}; 

... 

EXPORT_API void detectMarkers(... , markerStruct *MarkerInfo) { 
    MarkerInfo->id = 3; 
    return; 
} 

C#

[DllImport ("ArucoUnity")] 
    public static extern void detectMarkers(... , 
     [MarshalAs(UnmanagedType.Struct)] ref MarkerStruct markerStruct); 

... 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
public struct MarkerStruct 
{ 
    public int Id; 
} 

... 

detectMarkers (d, W, H, d.Length, ref markerInfo);  
print(markerInfo.Id); 

回答

5

您正在返回一個指向本地變量的指針,該變量在.NET可以讀取之前已經被銷燬。在純C++中這是一個壞主意,而在p/invoke中是一個壞主意。

相反,有C#傳遞一個指向結構(只需使用ref關鍵字)和C++代碼,只需填寫進去。

+0

我試過使用ref,但是我仍然沒有設法獲得正確的值......你可能看看我編輯的問題嗎? – mkolarek

+0

@kolarek:就像我在我的回答中所說的,當你使用'ref'或'out'關鍵字時,C#實際上會傳遞一個指針。因此,在C++端使用'void detectMarkers(/*...*/ markerStruct * MarkerInfo)',然後使用'MarkerInfo-> id = 3;'。此外,擺脫p/invoke簽名中的'In'屬性,這意味着不從C++獲取數據,這顯然與您想要的相反。 –

+0

非常感謝,我已經完成了! – mkolarek

3

MarkerInfo變量是LOC並在函數返回時超出範圍。 不要返回指向局部變量的指針,它們指向的對象將不再存在。

+0

謝謝!你有什麼我應該做的建議嗎? – mkolarek

0

打算給這個一掄...的職位THX ...

// new struct and generic return for items to 
struct _itemStruct 
{ 
    unsigned int id; // 0 by default, so all lists should start at 1, 0 means unassigned 
    wchar_t *Name; 
}; 

// for DLL lib precede void with the following... 
// EXPORT_API 
void getItems(std::vector<_itemStruct *> *items) 
{ 
    // set item list values here 


    //unsigned char *bytePtr = (unsigned char*)&items; // manual pointer return 

    return; 
}; 

/* // In theory c# code will be... 
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
public struct _itemStruct 
{ 
    public unsigned int Id; 
    public string Name; 
} 

[DllImport ("ListOfItems")] // for ListOfItems.DLL 
public static extern void getItems(
[MarshalAs(UnmanagedType.Struct)] ref List<_itemStruct> items); 
// */ 
相關問題