简体   繁体   English

将大小未知的数组从非托管代码传递到托管代码

[英]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*Height Buf的尺寸为宽*高

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM