我主要是一个C#dev(自大学以来没有多少C ++),但我正致力于将大量现有C ++代码集成到应用程序中。我有一个C ++ / CLI程序集正在缓冲这两个世界,并且从C#到C ++的通信工作正常。我的问题是,C ++类有一个方法调用,它生成一个二进制blob(想想在C#世界中byte
的数组),我需要在C#中进行处理(像一个固体包一样传递) 。
我正在寻找的是如何在两个世界之间处理缓冲区/包装器方法(C ++ / CLI)的建议。我假设我传递char*
和长度,但C#将其视为byte*
(我假设这是一些C ++ / CLI“魔术”)。
我也试过传递array<Byte ^>^
,但是没有太多运气将char*
从C ++ lib的其余部分转换为byte
数组......以及我所拥有的内容闻起来不错。
答案 0 :(得分:3)
让C ++ / CLI代码将System::IO::UnmanagedMemoryStream
移交给C#代码,然后可以在所述流上使用System.IO.BinaryReader
来根据需要提取数据。
顺便说一句,C ++ / CLI的char
与C#的sbyte
是同义词,C ++ / CLI的unsigned char
与C#的byte
同义,C ++ / CLI的wchar_t
}是C#的char
的同义词,而C ++ / CLI的array<unsigned char>^
与C#的byte[]
同义。请注意,它是array<unsigned char>^
或array<System::Byte>^
而非array<unsigned char^>^
或array<System::Byte^>^
,因为System.Byte
是值类型而非ref类型。
答案 1 :(得分:3)
您可以使用UnmanagedMemoryStream,如下所示:
byte[] message = UnicodeEncoding.Unicode.GetBytes("Here is some data.");
IntPtr memIntPtr = Marshal.AllocHGlobal(message.Length);
byte* memBytePtr = (byte*) memIntPtr.ToPointer();
UnmanagedMemoryStream writeStream = new UnmanagedMemoryStream(memBytePtr, message.Length, message.Length, FileAccess.Write);
writeStream.Write(message, 0, message.Length);
writeStream.Close();
反向路线,粗略地说:
UnmanagedMemoryStream readStream = new UnmanagedMemoryStream(memBytePtr, message.Length, message.Length, FileAccess.Read);
byte[] outMessage = new byte[message.Length];
readStream.Read(outMessage, 0, message.Length);
readStream.Close();
// Convert back into string for this example
string converted = UnicodeEncoding.Unicode.GetString(outMessage);
Marshal.FreeHGlobal(memIntPtr);
我确信MSDN会有更多资源
答案 2 :(得分:2)
我拍了一下它并想出了这个。没什么了不起的,只需分配托管数组,复制数据并将其返回。
头:
#pragma once
using namespace System;
using namespace System::Runtime::InteropServices;
namespace CLRLib
{
public ref class TwiddlerFunctions
{
public:
static array< Byte >^ GetArray();
};
}
实现:
#include "CLRLib.h"
array< Byte >^ CLRLib::TwiddlerFunctions::GetArray()
{
unsigned char data[] = { 1, 2, 34, 5 };
// convert the unmanaged array to a managed array
array< Byte >^ arr = gcnew array< Byte >(sizeof data);
Marshal::Copy((IntPtr)data, arr, 0, arr->Length);
return arr;
}
C#方:
using System;
using CLRLib;
class Program
{
static void Main(string[] args)
{
byte[] arr = TwiddlerFunctions.GetArray();
Console.WriteLine(String.Join(" ", arr)); // 1 2 34 5
}
}