【问题标题】:Preserve C++ Pointer in C#在 C# 中保留 C++ 指针
【发布时间】:2020-04-18 14:18:46
【问题描述】:

我正在用 C# 编写一个小程序,其中包括一个 C++ Dll。

在 C++ 中,有许多类需要实例化并留待以后使用。 这看起来像以下函数:

C++:
__declspec(dllexport) FrameCapture* GetFrameCapturer(HWND windowHandle) {
    ProcessWindow* window = ProcessWindowCollection::GetInstance()->FindWindow(windowHandle);
    FrameCapture* capture = new FrameCapture(window);
    return capture;
}

如您所见,我只是创建了一个 FrameCapture 类并返回一个指向它的指针。

此指针作为 IntPtr 存储在 C# 中。

C#:
[DllImport("<dllnamehere>")]
public static extern IntPtr GetFrameCapturer(IntPtr windowHandle);

到目前为止,这非常有效。 但是,如果我使用该指针来获取 FrameCapture 的实例

C++:
__declspec(dllexport) BITMAPFILEHEADER* GetBitmapFileHeader(FrameCapture* frameCapturer) {
    return frameCapturer->GetBitmapFileHeader();
}

该类将完全是空的。 如何获取我在第一步中初始化的类的实例?

编辑:

我做了一些测试并将指针替换为更好看的整数。

我将“捕获”转换为 Int32 并将其返回。 在我的测试用例中,它返回字节(208,113,244,194)。 正如预期的那样,这些值在 C++ 和 C# 中是相同的。

但是,现在变得奇怪了。

如果我将此 Int32 传递给“GetBitmapFileHeader”,则值会突然变为 byte(184,231,223,55)。

这还不算接近!我想到了 Little Big Endian 或类似的东西,但是,这是一个全新的 Memoryblock?

IntPtr 将继续执行相同的行为。

根据要求,我还发布了“GetBitmapFileHeader”的导入

[DllImport("<dllnamehere>")]
public static extern tagBITMAPFILEHEADER GetBitmapFileHeader(IntPtr capturerHandle);

【问题讨论】:

  • 你如何在 C# 端存储GetFrameCapturer的结果?
  • @UnholySheep 将其存储为类的字段。 [...] 私有 IntPtr m_capturerHandle; [...] 然后作为参数传递给 GetBitmapFileHeader
  • 那我真的不明白问题可能出在哪里。这里没有什么会导致对象同时被释放将指针变为空指针
  • GetBitmapFileHeader 导入在哪里?
  • 贴出相关的C#代码。

标签: c# c++ pointers interopservices


【解决方案1】:

好的,我明白了。

从 C# 中查看此导入。

C#:
[DllImport("<dllnamehere>")]
public static extern tagBITMAPFILEHEADER GetBitmapFileHeader(IntPtr capturerHandle);

错了!

该函数现在返回一个 IntPtr,它完全可以正常工作。

这是新的设置:

C++:

    __declspec(dllexport) void* __stdcall GetBitmapFileHeader(void* frameCapturer) {

        FrameCapture* cap = (FrameCapture*)frameCapturer;
        return cap->GetBitmapFileHeader();
    }

C#:

[DllImport("libWinCap.dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetBitmapFileHeader(IntPtr frameCapturer);

[...]
//calling
IntPtr ptr = GetBitmapFileHeader(m_capturerHandle);
m_bitmap.m_fileHeader = (tagBITMAPFILEHEADER)Marshal.PtrToStructure(ptr, typeof(tagBITMAPFILEHEADER));

我现在只移动指针并使用 PtrToStructure 来读取内存。

另外,感谢您的每条评论。

【讨论】:

    猜你喜欢
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 2018-03-16
    • 2011-06-27
    • 2017-04-17
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    相关资源
    最近更新 更多