我们有一个任务可以将一个类的引用传递给另一个从C#到C++的类。 C#类看起来是这样的:Marshal C#类与C++的参考成员
[StructLayout(LayoutKind.Sequential, Pack=1)]
public class ImageInfo
{
public uint Width;
public uint Height;
public uint Stride;
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
internal class FrameInfo
{
public int FrameNumber;
public double TimeStamp;
public ImageInfo Image; // This is the problem
}
C++结构看起来像这样(包也是1):
struct FrameInfo
{
public:
unsigned int frameNumber;
double timeStamp;
ImageInfo *image;
};
struct ImageInfo
{
public:
unsigned int m_width;
unsigned int m_height;
unsigned int m_stride;
};
我们通过C#类C++这样的方式:
[DllImport("ourLib.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern int OnFrame(int pId, FrameInfo pFrame);
并接受它在C++:
extern "C" __declspec(dllexport) int OnFrame(int pId, const FrameInfo *pFrame);
作为一个资源ult在FrameInfo
结构体中我们没有引用,只是嵌入类。内存布局是这样的:而不是
0..3 bytes: uint frameNumber
4..11 bytes: double timeStamp
12..15 bytes: uint width
16..19 bytes: uint height
etc...
:
0..3 bytes: uint frameNumber
4..11 bytes: double timeStamp
12..15 bytes: ImageInfo* image // pointer to the image
类嵌入导致额外的数据复制,使我们很不高兴。我们试图通过引用作为IntPtr
与Marshal.StructureToPtr()
的帮助,但MSDN说,
“StructureToPtr副本结构的内容为内存的预分配块”
也使其副本数据。
然后,我们尝试在C#中使用C风格的指针:
[StructLayout(LayoutKind.Sequential, Pack=1)]
internal unsafe class FrameInfo
{
public int FrameNumber;
public double TimeStamp;
public ImageInfo *Image;
}
编译器说,“不能走的地址,获取的大小,或指针声明为管理型”
好的。然后,我们尝试了一个奇怪的未记录的函数__makeref()
,然后将其转换为IntPtr,但它也具有相当奇怪的内存布局。
那么,有没有什么办法像往常一样引用参考?
你试过从'MarshalByRefObject'派生'ImageInfo'吗? –