如何在winapi-rs中获取IWICImagingFactory实例

How to acquire instance of IWICImagingFactory in winapi-rs

所以在 my previous question I was advised to convert byte buffers to IStream via SHCreateMemStream and use IWICImagingFactory::CreateDecoderFromStream. The first part already caused some complications as winapi-rs did contain an implementationIStream 而不是函数本身 - 谢天谢地 winapi-rs 包含了我 link 所需的一切,如下所示:

pub type HIStream = *const IStream;

extern "system" {
    pub fn SHCreateMemStream(pbInit: *const BYTE, cbInit: UINT) -> HIStream;
}

。 现在我遇到了与 IWICImagingFactory class 类似的问题,我需要调用 CreateDecoderFromStream 方法。然而,根据 documentation 它需要一个 &self 参数并且类似于 IStream 是我理解的一个特征。如何在不从头开始实施的情况下获得 IWICImagingFactory 的新实例。我看到有人谈论一个叫做 CoCreateInstance 的函数和一些 com API 的细节,但那不是很清楚,因为我现在对 com API 的理解很差。

感谢评论中的建议,我通过查看 WIC API Overview 找到了一种方法 - 但是由于一些问题,我想添加允许我这样做的代码事情。 (这绝不是一个很好的防锈代码 - 但它确实有效)。

let mut pFactory: *mut c_void = uninitialized();
let hr = CoCreateInstance(&CLSID_WICImagingFactory as *const IID,
                                              null_mut(),
                                              CLSCTX_INPROC,
                                              &IWICImagingFactory::uuidof(),
                                              &mut pFactory as *mut *mut c_void);

P.S。 std::mem::uninitialized 已弃用且不安全且显然很糟糕,请记住这一点。

您的 与我的做法很接近。下面的代码有两个优点:

  • 它生成一个正确类型的接口指针(*mut IWICImagingFactory)
  • 不依赖uninitialized()
let mut factory: *mut IWICImagingFactory = std::ptr::null_mut();
let hr = unsafe {
    CoCreateInstance(
        &CLSID_WICImagingFactory,
        std::ptr::null_mut(),
        CLSCTX_INPROC_SERVER,
        &IWICImagingFactory::uuidof(),
        &mut factory as *mut *mut _ as *mut *mut _,
    )
};

这样你就有了一个指向 IWICImagingFactory 的指针,你可以立即使用,例如

let mut decoder: *mut IWICBitmapDecoder = std::ptr::null_mut();
let hr = unsafe {
    (*factory).CreateDecoderFromStream(
        &mut stream,  // An IStream providing the image data
        std::ptr::null_mut(),
        options,      // Needs to be constructed elsewhere
        &mut decoder as *mut *mut _ as *mut *mut _,
    )
};

错误处理和资源管理大部分是手动的,代码中省略了(您可以使用 FAILED 函数来确定成功或失败。错误退出仍然需要您通过相应的调用来清理Release.

windows crate 为 COM 接口提供资源管理包装器,使清理成为堆栈展开的一部分。最终效果是错误传播远没有那么冗长和手动。如果您有兴趣,我也可以提供基于 windows crate 的解决方案。