2014-01-07 22 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属性将这些指向字符串? –