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