2014-01-07 64 views
0

我有其中一個結構的定義如下一個C++機DLL:在C++ DLL作爲Pinvoking不復制整個字符串

typedef struct 
{ 
int x; 
int y; 
unsigned short* orange; 
}SET_PROFILE; 

和一個功能:

extern "C" _declspec(dllexport) void modifyClass(SET_PROFILE** input) 
{ 
    *input = &globPro; 
} 

其中globPro是一個全局SET_PROFILE類型的對象,其成員橙色是「ABC」。

我已經重新定義該結構上的C#側爲一類:

[StructLayout(LayoutKind.Sequential)] 
public class SET_PROFILE 
{ 
    public int x; 
    public int y; 
    public String orange; 
} 

和pinvoking功能:

[DllImport("Project2.dll", CallingConvention = CallingConvention.Cdecl)] 
static extern void modifyClass(out IntPtr input); 

當我調用此函數,然後marhal回以下結構:

IntPtr classPtr = IntPtr.Zero; 
classPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SET_PROFILE))); 
modifyClass(out classPtr); 
profile1 = (SET_PROFILE)Marshal.PtrToStructure(classPtr, typeof(SET_PROFILE)); 

現在,profile1的orange meber只有「A」而不是「ABC」。它與如何使用指針進行復制有關。但是我不能修改C++函數。 是因爲我使用了一個字符串作爲C#類的成員而不是unsigned short []。我也嘗試過,但失敗了。

+0

這是一個Unicode字符串,默認編組假設'字符*'。這就是爲什麼你只得到單個字母,'A'之後有一個額外的二進制零。使用CharSet = CharSet.Unicode或Marshal.PtrToStringUni()。 –

+0

謝謝。我編輯的dll導入包括CharSet = CharSet.Unicode,但它仍然顯示一個字母。我不能使用Marshal.PtrToStringUni(),因爲我作爲一個整體處理類而不僅僅是它的字符串成員。 –

+0

你做錯了。您應該將結構體的值複製到調用者的變量中,並通過引用傳遞。您不應該返回一個指向DLL中的全局變量的指針。如果你需要返回一個指針,就這樣做。作爲返回值。我不認爲你完全理解你在做什麼。我想幫助你理解。 –

回答

1

嘗試使用以下:

[StructLayout(LayoutKind.Sequential)] 
public class SET_PROFILE 
{ 
    public int x; 
    public int y; 

    public System.IntPtr orange;  
    public string OrangeString { get { return Marshal.PtrToStringAnsi(orange); } } 
} 
+0

這裏,是orangeString成員的屬性? –

+0

@TylerDurden不,這是一個屬性,我會更新套管。 – Matt

+0

不錯。有效。所以使用一個IntPtr,你指向它的位置,當它在C++中,然後在C#端,orangestring屬性將這些指向字符串? –