gpt4 book ai didi

c# - 将字符串数组从 C# 传递到 C++ - 内存管理

转载 作者:太空宇宙 更新时间:2023-11-04 12:18:00 28 4
gpt4 key购买 nike

在我的代码中,我有一个接受字符串数组的 c DLL:void Helper::ProcessEvent(PEVENT_RECORD pEvent,wchar_t** OutPutFormattedData)

我用这段代码调用它:

[DllImport("Helper.dll", EntryPoint = "ProcessEvent")]
internal static extern uint ProcessEvent(
[In, Out]
ref EVENT_RECORD pEvent,
[In, Out]
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] ref string[] pResult);

在 C++ 代码中,这里是我用来填充数组的主要代码:

for(int i=0;i<list.Size;i++)
{
EventWrapperClass *EWC = new EventWrapperClass();
EWC = list.Events[i];
OutPutFormattedData[i] = new wchar_t [wcslen(HelperFormatMessage(L"%s: %s\n",EWC->GetProperyName(),EWC->GetProperyValue()))+1];
wcscpy(OutPutFormattedData[i] ,HelperFormatMessage(L"%s: %s\n",EWC->GetProperyName(),EWC->GetProperyValue()));

调用代码:

string[] strArr= new string[1];
NativeHelper.ProcessEvent(ref eventRecord, ref strArr);

我有两个问题:

  1. 为什么在调用此函数后我在 c# 中检查传递的数组的值时发现它是空的(数据存在于 c++ 代码中,我调试过)?

  2. 如果我在 c++ dll 中分配内存,我需要在哪里释放它?在 C++ 或 C# 中?

非常感谢!

编辑:

C++ 的签名:

static __declspec(dllexport) void ProcessEvent(PEVENT_RECORD pEvent, wchar_t** OutPutFormattedData);

最佳答案

如果您在 C# 中分配一个(托管或非托管)缓冲区(或数组或字符),然后填写 C++:
1.在C#中解除分配。
2. Buffer 应该是 [in] 并且在 C# 签名中没有 ref 或 out。

如果在 C++ 中分配缓冲区(或字符数组):
1. 将缓冲区作为 [out] out IntPtr 传递。
2. C++签名添加deallocate方法
3.将缓冲区复制到C#缓冲区或新字符串
4. 使用 IntPtr 从 C# 调用 C++ deallocater。

您可以使用 System.Runtime.InteropServices.Marshal 在 C# 中分配/解除分配非托管内存。不要用于释放在 .NET 外部分配的内存!

System.Runtime.InteropServices.Marshal 也可用于将内存从外部缓冲区 (IntPtr) 复制到 .NET 缓冲区或字符串。

将导入的方法标记为私有(private)方法,并用使用 .NET 参数的公共(public)(或 protected 或内部)方法包装(例如,使用 System.Runtime.InteropServices.Marshal.Copy 并调用外部释放)。

C++:

int ProcessEvent(PEVENT_RECORD eventData, wchar_t*& message)
{
// example code
message = new wchar_t[100];
if (message == 0)
return 1;
}

void DeallocateString(wchar_t* array)
{
delete[] arrayPtr;
}

wchar_t* ErrorCodeToMessage(int errorCode)
{
switch (errorCode)
{
case 0: return 0; // return NULL pointer
case 1: return L"No!!!";
default: return L"WTF!?";
}
}

C#:

[DllImport("Helper.dll", EntryPoint = "ProcessEvent")]
private static extern uint ProcessEventExternal(
[In, Out] ref EventData eventData,
[In, Out, MarshalAs(UnmanagedType.SysInt))] ref IntPtr resultMessages);

[DllImport("Helper.dll", EntryPoint = "DeallocateString")]
private static extern voidDeallocateStringExternal(
[In, MarshalAs(UnmanagedType.SysInt)] IntPtr arrayPtr);

[DllImport("Helper.dll", EntryPoint = "ErrorCodeToMessage")]
private static extern
[return: MarshalAs(UnmanagedType.SysInt)] IntPtr
ErrorCodeToMessageExternal(int errorCode);

public string ProcessEvent(ref EventData eventData)
{
IntPtr resultPtr = IntPtr.Zero;
uint errorCode = ProcessEventExternal(eventData, ref resultPtr);

if (errorCode != null)
{
var errorPtr = ErrorCodeToMessageExternal(errorCode);

// returns constant string - no need to deallocate
var errorMessage = Marshal.PtrToStringUni(errorPtr);

throw new ApplicationException(errorMessage);
}

var result = Marshal.PtrToStringUni(resultPtr);
ExternalDeallocate(resultPtr);

return result;
}

关于c# - 将字符串数组从 C# 传递到 C++ - 内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6682011/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com