gpt4 book ai didi

c# - 将具有 C++ 引用成员的 C# 类编码

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:38:50 25 4
gpt4 key购买 nike

我们的任务是将一个类与另一个类的引用从 C# 传递到 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++ 结构看起来像这样(pack 也是 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);

作为 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

类嵌入会导致额外的数据复制,这让我们非常沮丧。我们试图在 Marshal.StructureToPtr() 的帮助下将引用作为 IntPtr 传递,但 MSDN 说

"StructureToPtr copies the contents of structure to the pre-allocated block of memory"

以便它也复制数据。

然后我们尝试在C#中使用C风格的指针:

[StructLayout(LayoutKind.Sequential, Pack=1)]
internal unsafe class FrameInfo
{
public int FrameNumber;
public double TimeStamp;
public ImageInfo *Image;
}

编译器说“无法获取托管类型的地址、大小或声明指向托管类型的指针”

好的。然后我们尝试了一个奇怪的未记录的函数 __makeref() 然后将它转换为 IntPtr 但它也有相当奇怪的内存布局。

那么,有没有什么办法可以像往常引用一样传递引用呢?

最佳答案

So, is there any way to pass the reference just as usual reference?

不,由于垃圾收集器,引用不稳定,必须先固定一个对象。 pinvoke 编码器拒绝为非平凡的对象图这样做。您必须将 FrameInfo.Image 成员声明为 IntPtr 并使用 GC.Alloc + AddrOfPinnedObject

在这种情况下,您可以某处,ImageInfo 应该是结构类型。这允许您声明一个指针:

[StructLayout(LayoutKind.Sequential)]
public struct ImageInfo {
public uint Width;
public uint Height;
public uint Stride;
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe class FrameInfo {
public int FrameNumber;
public double TimeStamp;
public ImageInfo* Image;
}

只要结构存储在堆栈中(局部变量或方法参数),您就可以轻松地初始化 FrameInfo.Image:

var info = new ImageInfo { Width = 5, Height = 6, Stride = 7 };
var frame = new FrameInfo { FrameNumber = 1, TimeStamp = 2, Image = &info };
OnFrame(42, frame);

关于c# - 将具有 C++ 引用成员的 C# 类编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31210620/

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