我对托管/非托管互操作非常陌生,因此我希望获得一些关于以下过程将位图从非托管 C++ 获取到托管 C# 的安全性的意见。基本思想是:
- C# 调用互操作函数,
FetchImage
,这是非托管 C++ 中的。它通过一个out int
param. FetchImage
有对应的long *
param.
- In C++,
FetchImage
创建一个CBitmap
在安全的地方,即不在本地,在上面画一些东西,使用HandleToLong()
转换位图的HBITMAP
句柄long
,将其存储在 C# 的参数中,然后返回。
- 回到 C# 中,
out int
参数被转换为IntPtr
和用途System.Drawing.Image.FromHbitmap
复制数据并生成System.Drawing.Bitmap
object.
- 然后 C# 调用另一个互操作函数,
ReleaseImage
.
- In C++,
ReleaseImage
释放与相关的资源CBitmap
它创建较早。
这就是不耐烦的人的要点。下面更具体的代码示例。
函数的 C++ 互操作定义:
namespace {
std::unique_ptr< CBitmap > bitty;
}
HRESULT __stdcall Helper::FetchImage( /*[out]*/ long * hBitmap )
{
bitty.reset( new CBitmap );
// call CreateBitmap and then draw something,
// ensure it's not selected into a DC when done
*hBitmap = HandleToLong( bitty->GetSafeHandle() );
return S_OK;
}
HRESULT __stdcall Helper::ReleaseImage()
{
bitty.reset();
return S_OK;
}
互操作函数的 IDL 原型,包装在 C# 中的辅助类中:
[id(1)] HRESULT FetchImage( long * hBitmap );
[id(2)] HRESULT ReleaseImage();
在辅助类中生成这些 C# 原型:
void FetchImage( out int hBitmap );
void ReleaseImage();
调用它们的 C# 看起来有点像这样:
int ret;
helper.FetchImage( out ret );
Bitmap b = Image.FromHbitmap( (IntPtr)ret );
helper.ReleaseImage();
// do anything I want with b
我自己提出的唯一问题是调用的情况FetchImage
or ReleaseImage
从其他地方让事情不同步。所以我可能会有一个清单CBitmap
s 而不是只有 1,然后将句柄传递回ReleaseImage
所以它只会破坏匹配的那个FetchImage
call.
有什么我不知道的陷阱吗?我确实有这个工作,我只是想确保我没有做危险的事情,因为我不知道更好。
您可以声明调用者有责任释放 HBITMAP。这将简化您的 C++ 代码,因为您可以删除 ReleaseImage 方法。例子:
HRESULT __stdcall Helper::FetchImage( /*[out]*/ HBITMAP * hBitmap )
{
*hBitmap = NULL; // assume failure
unique_ptr<CBitmap> bmp(new CBitmap);
// call CreateBitmap and then draw something,
// ensure it's not selected into a DC when done
*hBitmap = (HBITMAP)bmp->Detach();
return S_OK;
}
// Delete ReleaseImage and all supporting global variables...
// C# example:
IntPtr ret;
helper.FetchImage( out ret );
try {
Bitmap b = Image.FromHbitmap( ret );
} finally {
DeleteObject(ret); // pinvoke call into GDI
}
或者,您可以考虑返回IPicture http://msdn.microsoft.com/en-us/library/ms680761%28VS.85%29.aspx using OleCreatePictureIndirect http://msdn.microsoft.com/en-us/library/ms694511%28VS.85%29.aspx。这提供了一些优点:
- 调用者使用标准 COM 引用计数释放返回的图像。这通常使调用者不必担心释放返回的图像(除非调用者是另一个需要手动调用 IUnknown::Release 的 C++ 程序)。
- 与其他支持 COM 的语言(例如 VBA / VB6)具有更好的兼容性。 IPicture 是在 COM 中传递图片的标准方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)