我在C#中有一个结构如下:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct UserProfileData
{
int userProfileRevision;
[MarshalAs(UnmanagedType.LPStr)]
public String firstName;
[MarshalAs(UnmanagedType.LPStr)]
public String lastName;
[MarshalAs(UnmanagedType.LPStr)]
public String memberids;
[MarshalAs(UnmanagedType.LPStr)]
public String emailAddress;
}
我传递了对此
的引用typedef struct userProfile
{
int profileRevision;
char *firstName;
char *lastName;
char *memberids;
char *emailAddress;
} userProfile_t;
我的C.dll具有这样的功能
int getUserProfileData(userProfile_t *pUserProfile);
获取上面结构中字符串的值。我从C#代码调用此函数,并正确填充int值'profileRevision'。像'firstname'这样的字符串在上面的C函数中正确地动态分配和填充,但是当代码返回到C#环境时,struct中的所有字符串都为null。处理这个问题的最佳方法是什么?
答案 0 :(得分:2)
您编写它的方式,char*
缓冲区在托管端分配。但那是错误的地方。分配发生在非管理方面。在C#中声明结构如下:
[StructLayout(LayoutKind.Sequential)]
public struct UserProfileData
{
int userProfileRevision;
public IntPtr firstName;
public IntPtr lastName;
public IntPtr memberids;
public IntPtr emailAddress;
}
然后调用getUserProfileData
,将结构作为out参数传递。或者可能是ref参数。我不知道它应该是什么。
您的DllImport
将如下所示(指定了正确的调用约定):
[DllImport(@"mydll.dll", CallingConvention=CallingConvention.???)]
private static extern int getUserProfileData(out UserProfileData userProfile);
然后将返回的指针转换为这样的字符串:
string firstName = Marshal.PtrToStringAnsi(userProfile.firstName);
等其他领域。
据推测,非托管代码还公开了一个释放结构中返回的内存的函数。完成结构后调用它。