包含字符串的元帅结构 - 在非托管 C 函数中接收到的字符串不正确
Marshal structure which contains strings - incorrect string received in unmanaged C function
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct sName_d
{
[MarshalAs(UnmanagedType.LPStr)]
public string szCountry;
[MarshalAs(UnmanagedType.LPStr)]
public string szCommonName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct sCertData_d
{
public Int32 dwVersion;
public sName_d sIssuer;
public sName_d sSubject;
}
public void GenerateCert()
{
sCertData_d cert = new sCertData_d();
sName_d caIssuer = new sName_d();
caIssuer.szCountry = "US";
caIssuer.szCommonName = "John";
sName_d caSubject = new sName_d();
caSubject.szCountry = "UK";
caSubject.szCommonName = "Johann";
cert.sIssuer = caIssuer;
cert.sSubject= caSubject;
NativeMethods.GenerateCert(ref cert);
}
上面代码中,NativeMethods.GenerateCert是C的非托管函数。
当 Call 到达此函数内部时,我没有获得字符串值 "John"、"UK"、"Johann" 和 "US"。
[DllImport("AuthLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int GenerateCert(ref sCertData_d cert);
非托管函数原型是这样的-
typedef struct sName_d
{
char szCountry[0x35];
char szCommonName[0x35];
}sName_d;
typedef struct sCertData_d
{
int version;
sName_d sIssuer;
sName_d sSubject;
}sCertData_d;
int GenerateCert(const sCertData_d *psCert);
您对 sName_d
的翻译有误。非托管结构是:
typedef struct sName_d
{
char szCountry[0x35];
char szCommonName[0x35];
} sName_d;
这些是内联字符数组。您将这些编组为 UnmanagedType.LPStr
。这是一个指向空终止字符串的指针。您需要使用 UnmanagedType.ByValTStr
.
Used for in-line, fixed-length character arrays that appear within a structure. The character type used with ByValTStr is determined by the System.Runtime.InteropServices.CharSet argument of the System.Runtime.InteropServices.StructLayoutAttribute attribute applied to the containing structure. Always use the MarshalAsAttribute.SizeConst field to indicate the size of the array.
.NET Framework ByValTStr types behave like C-style, fixed-size strings inside a structure (for example, char s[5]
).
您的翻译应该是:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct sName_d
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x35)]
public string szCountry;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x35)]
public string szCommonName;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct sName_d
{
[MarshalAs(UnmanagedType.LPStr)]
public string szCountry;
[MarshalAs(UnmanagedType.LPStr)]
public string szCommonName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct sCertData_d
{
public Int32 dwVersion;
public sName_d sIssuer;
public sName_d sSubject;
}
public void GenerateCert()
{
sCertData_d cert = new sCertData_d();
sName_d caIssuer = new sName_d();
caIssuer.szCountry = "US";
caIssuer.szCommonName = "John";
sName_d caSubject = new sName_d();
caSubject.szCountry = "UK";
caSubject.szCommonName = "Johann";
cert.sIssuer = caIssuer;
cert.sSubject= caSubject;
NativeMethods.GenerateCert(ref cert);
}
上面代码中,NativeMethods.GenerateCert是C的非托管函数。 当 Call 到达此函数内部时,我没有获得字符串值 "John"、"UK"、"Johann" 和 "US"。
[DllImport("AuthLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int GenerateCert(ref sCertData_d cert);
非托管函数原型是这样的-
typedef struct sName_d
{
char szCountry[0x35];
char szCommonName[0x35];
}sName_d;
typedef struct sCertData_d
{
int version;
sName_d sIssuer;
sName_d sSubject;
}sCertData_d;
int GenerateCert(const sCertData_d *psCert);
您对 sName_d
的翻译有误。非托管结构是:
typedef struct sName_d
{
char szCountry[0x35];
char szCommonName[0x35];
} sName_d;
这些是内联字符数组。您将这些编组为 UnmanagedType.LPStr
。这是一个指向空终止字符串的指针。您需要使用 UnmanagedType.ByValTStr
.
Used for in-line, fixed-length character arrays that appear within a structure. The character type used with ByValTStr is determined by the System.Runtime.InteropServices.CharSet argument of the System.Runtime.InteropServices.StructLayoutAttribute attribute applied to the containing structure. Always use the MarshalAsAttribute.SizeConst field to indicate the size of the array. .NET Framework ByValTStr types behave like C-style, fixed-size strings inside a structure (for example,
char s[5]
).
您的翻译应该是:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct sName_d
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x35)]
public string szCountry;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x35)]
public string szCommonName;
}