没有太多 C++ 经验。尝试使用
char*
将 C 中的 string
编组到 C# 中的 [MarshalAs(UnmanagedType.LPStr)]
,但我得到了 "a heap has been corrupted" exception
。但它确实可以反向工作(C# 中的 string
到 C 中的 char*
)。我在这里做错了什么?
更多详情: 在 C 端,这是结构:
struct STRUCTV
{
char* _pretext;
char* _result;
};
这是 C 函数签名:
void add_all_numbers(STRUCTV *structV);
这是C#方面
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct STRUCTV
{
[MarshalAs(UnmanagedType.LPStr)]
public string _pretext;
[MarshalAs(UnmanagedType.LPStr)]
public string _result; //<----THIS ISNT WORKING
}
internal partial class NativeMethods
{
[DllImport(
"Library.dll",
EntryPoint = "function1",
CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
public static extern void function1(ref STRUCTV structV);
}
这就是我的使用方式:
STRUCTV myStruct = new STRUCTV();
myStruct._pretext = "Pretext";
myStruct._result = null;
NativeMethods.function1(ref myStruct); //<---- ntdll.dll : A heap has been corrupted"
Console.WriteLine(myStruct._result);
如果这很重要,这就是 C 代码内部发生的情况(如果这很重要):
string resultstring = GetResult();
char* result = new char[resultstring.length() + 1];
strcpy_s(result, resultstring.length() + 1, resultstring.c_str());
structV->_result = result;
一些附加信息。如果我不将 char* 编组为 _result 中的字符串,它就会起作用,并且我想了解原因。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct STRUCTV
{
[MarshalAs(UnmanagedType.LPStr)]
public string _pretext;
public IntPtr _result;
}
STRUCTV myStruct = new STRUCTV();
myStruct._pretext = "Pretext";
myStruct._result = IntPtr.Zero;
NativeMethods.function1(ref myStruct);
string resultString = Marshal.PtrToStringAnsi(myStruct._result);
Console.WriteLine(resultString);
C# 代码假设它负责将字符串数据传递给 C++ 代码。但是,C++ 代码实际上是分配字符串数据并将其返回给 C# 代码。因此,您无法按照您尝试的方式用
LPStr
对其进行编组,因为它是输出数据而不是输入数据。
使用
IntPtr
是此处的正确操作。您可以使用 Marshal.PtrToStringAnsi()
将 IntPtr
转换为 C# string
。
但是,还要注意,C++ 代码正在对字符串数据进行
new[]
操作,而 C# 无法释放该内存。因此,您必须从 C++ 导出另一个函数,C# 代码可以调用该函数将 IntPtr
传回 C++,以便它可以正确地 delete[]
内存。