[英]Passing structure with array of unknown size from unmanaged to managed code
I have a problem passing void pointer from unmanaged code to managed. 我将无效指针从非托管代码传递到托管时遇到问题。 There is a function's pointer in .cpp file .cpp文件中有一个函数的指针
TESTCALLBACK_FUNCTION testCbFunc;
TESTCALLBACK_FUNCTION takes C++ structure TESTCALLBACK_FUNCTION采用C ++结构
typedef void (*TESTCALLBACK_FUNCTION )(TImage image);
struct TImage
{
int Width; //width
int Height; //height
void *Buf; //data buffer
};
C# function and structure 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 passed to unmanaged code and when it's called I receive exception. TImageReceived传递给非托管代码,并且在调用它时会收到异常。
System.Runtime.InteropServices.SafeArrayTypeMismatchException System.Runtime.InteropServices.SafeArrayTypeMismatchException
If I passed NULL in field Buf from unmanaged code everything will works fine. 如果我在非托管代码的字段Buf中传递了NULL ,那么一切都会正常进行。
I know about MarshalAs atrribute, but the problem is that I cannot use SizeConst because Buf size is always different. 我知道MarshalAs属性,但是问题是我不能使用SizeConst,因为Buf大小总是不同的。 But it always has size of Width*Height. 但它始终具有Width * Height的大小。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=???)]
How to cast void* from unmanaged to managed code? 如何将void *从非托管代码转换为托管代码?
Based on your comment, and assuming that TImage
from your C++ code maps neatly on to your struct (Warning - if you're using TImage
from the Borland VCL, then that might not map on as neatly as you're hoping) 根据您的评论,并假设C ++代码中的TImage
巧妙地映射到您的结构上(警告-如果您使用的是Borland VCL中的TImage
,则可能不会像您希望的那样巧妙地映射)
Buf
has a size Width*HeightBuf
的尺寸为宽*高
Your best option is to use Marshal.Copy
, for example 最好的选择是使用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);
}
Related: Marshalling struct with embedded pointer from C# to unmanaged driver 相关: 具有从C#到非托管驱动程序的嵌入式指针的编组结构
... However ... ... 但是 ...
If TImage
belongs to Borland's VCL then I would suggest re-thinking the struct, because it will involve marshalling other data inherited from TImage
's base class (Borland's documentation is unclear about the class' layout) - in which case, it would be easier to pass the arguments directly: 如果TImage
属于Borland的VCL,那么我建议重新考虑该结构,因为它将涉及整理从TImage
的基类继承的其他数据(Borland的文档不清楚该类的布局)-在这种情况下,这会更容易直接传递参数:
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.
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.