我有一个问题,将void指针从非托管代码传递给托管。 .cpp文件中有一个函数指针
TESTCALLBACK_FUNCTION testCbFunc;
TESTCALLBACK_FUNCTION采用C ++结构
typedef void (*TESTCALLBACK_FUNCTION )(TImage image);
struct TImage
{
int Width; //width
int Height; //height
void *Buf; //data buffer
};
C#功能和结构
public void TImageReceived(TImage image)
{
// logic
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1), Serializable]
public struct TImage
{
public int Width;
public int Height;
public IntPtr Buf;
}
TImageReceived 传递给非托管代码,当它被调用时,我收到异常。
System.Runtime.InteropServices.SafeArrayTypeMismatchException
如果我从非托管代码中传递字段Buf中的 NULL ,一切都会正常工作。
我知道Marshal是atrribute,但问题是我不能使用SizeConst,因为Buf大小总是不同的。但它的大小总是宽*高。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=???)]
如何将void *从非托管代码转换为托管代码?
答案 0 :(得分:1)
根据您的评论,并假设您的C ++代码中的TImage
整齐地映射到您的结构(警告 - 如果您正在使用Borland VCL中的TImage
,那么可能不会映射到像你希望的那样整洁;
Buf
的大小宽度*高度
您最好的选择是使用Marshal.Copy
,例如
using System.Runtime.InteropServices;
/* ... */
[StructLayout(LayoutKind.Sequential)]
public struct TImage
{
public int Width;
public int Height;
public IntPtr Buf;
}
/* ... */
public void TImageReceived(TImage image)
{
var length = image.Height * image.Width;
var bytes = new byte[length];
Marshal.Copy(image.Buf, bytes, 0, length);
}
相关: Marshalling struct with embedded pointer from C# to unmanaged driver
... <强>然而强> ...
如果TImage
属于Borland的VCL,那么我建议重新考虑这个结构,因为它将涉及编组继承自TImage
基类的其他数据(Borland的文档不清楚该类' layout) - 在这种情况下,直接传递参数会更容易:
public void TImageReceived(IntPtr buf, int width, int height)
{
var length = height * width;
var bytes = new byte[length];
Marshal.Copy(buf, bytes, 0, length);
// etc.
}