gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 05:49:43 24 4
gpt4 key购买 nike

我在将 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com