我有一个在 Unity 项目中使用的 C# 脚本。 C# 脚本导入一个 Dll,这是我用 C++ 编写的函数。在我的 C# 脚本中,我想调用 C++ 函数,对函数返回的数据执行某些操作,然后释放所有内存。我很困惑,因为我认为 Marshal.FreeHGlobal() 是调用的正确函数,但它在实践中会导致错误。我认为我不应该释放 C++ 函数中的内存,因为当该函数在 C# 中返回时我仍然需要使用数据。这是我正在使用的两个函数以及我认为属于 Marshal.FreeHGlobal() 的注释
C#
void OnMessage(Message message) {
byte[] byteArray =
message.payload.ToByteArray();
int currentFrameWidth = (int)message.payload.Width;
int currentFrameHeight = (int)message.payload.Height;
int decodedFrameLength;
IntPtr output = MyCppFunction(
byteArray, byteArray.Length, out decodedFrameLength);
byte[] resultByteArray = new byte[decodedFrameLength];
Marshal.Copy(output, resultByteArray, 0, decodedFrameLength);
// Attempting to call this causes an error "free(): invalid pointer"
// Marshal.FreeHGlobal(output);
Debug.Log("decoded frame length was: " + decodedFrameLength + " and resultByteArray length was: " + resultByteArray.Length);
if (resultByteArray.Length > 0) {
//Do stuff with resultByteArray
}
}
C++
unsigned char* MyCppFunction(const unsigned char* messagePtr,
int messageSize, int* decodedFrameLength) {
std::vector<uint8_t> decoded_img(33554432);
int decoded_len = 0;
decoder_->DecodeFrame(
reinterpret_cast<const unsigned char*>(messagePtr), messageSize,
reinterpret_cast<unsigned char*>(decoded_img.data()), &decoded_len,
33554432);
*decodedFrameLength = decoded_len;
unsigned char* outputData = new unsigned char[decoded_len];
std::memcpy(outputData, reinterpret_cast<unsigned char*>(decoded_img.data()),
decoded_len);
return outputData;
}
你不能依赖 C# 来理解 C++ 的内存分配在做什么。您需要从 C# 端传入一个缓冲区。
C++ 中类似以下内容
void MyCppFunction(
const unsigned char* messagePtr,
int messageSize,
unsigned char* outputData,
int* decodedFrameLength)
等效的
DllImport
看起来像这样:
[DllImport("libraryname.dll")]
void MyCppFunction(
byte[] messagePtr,
int messageSize,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
byte[] outputData,
ref int decodedFrameLength);
您根本不需要整理任何内容,因为这一切都是自动完成的。
void OnMessage(Message message)
{
byte[] byteArray =
message.payload.ToByteArray();
int currentFrameWidth = (int)message.payload.Width;
int currentFrameHeight = (int)message.payload.Height;
int decodedFrameLength = 33554432;
byte[] resultByteArray = new byte[decodedFrameLength];
IntPtr output = MyCppFunction(
byteArray, byteArray.Length, buffer, ref decodedFrameLength);
//
}