c# - 将具有未知大小数组的结构从非托管代码传递到托管代码

标签 c# c++ marshalling void-pointers

我在将 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,一切都会正常工作。

我知道 MarshalAs 属性,但问题是我不能使用 SizeConst,因为 Buf 大小总是不同的。但它的大小始终为 Width*Height。

[MarshalAs(UnmanagedType.ByValArray,SizeConst=???)]

如何将 void* 从非托管代码转换为托管代码?

最佳答案

根据您的评论,并假设您的 C++ 代码中的 TImage 巧妙地映射到您的结构(警告 - 如果您使用 Borland VCL 中的 TImage,那么这可能不会像您希望的那样整齐地映射)

Buf has a size Width*Height

例如,您最好的选择是使用 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 的文档不清楚类的布局)——在这种情况下,直接传递参数会更容易:

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.
}

关于c# - 将具有未知大小数组的结构从非托管代码传递到托管代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35519729/

相关文章:

c# - 将十进制列表转换为由分隔符 (',' 分隔的字符串)

c++ - 如何在不使用 boost 或创建模板的情况下在 C++ 中同时对两个 vector 进行排序?

.net - 在编码包装通过传递接口(interface)句柄工作的 C++ 接口(interface)(全部抽象)时 Intptr 是否足够?

c# - LINQ/IEnumerable Skip().Take() 效率与 "yield return"一起使用

c# - 在 WCF 中使用任务构建异步操作契约(Contract)的正确方法

c# - 如何从服务器 SSL 证书获取机器名

c++ - 为什么我在取消引用指针和不取消引用指针的情况下得到相同的值

c++ - 带空小部件的 Qt 拆分器

c# - 通过 COM 互操作将 C# 字典编码到 C++

json - 实现实体组件系统的最佳方式是什么