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

Posted

技术标签:

【中文标题】如何在winapi-rs中获取IWICImagingFactory的实例【英文标题】:How to acquire instance of IWICImagingFactory in winapi-rs 【发布时间】:2021-10-22 14:49:48 【问题描述】:

所以在my previous question 中,我被建议通过SHCreateMemStream 将字节缓冲区转换为IStream 并使用IWICImagingFactory::CreateDecoderFromStream。第一部分已经引起了一些复杂性,因为 winapi-rs 确实包含 implementation 用于 IStream 但不是函数本身 - 谢天谢地 winapi-rs 包含我需要链接它的所有内容,如下所示:

pub type HIStream = *const IStream;

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

。 现在我面临与IWICImagingFactory 类类似的问题,我需要调用CreateDecoderFromStream 方法。但是,根据documentation,它需要一个&self 参数,并且与IStream 类似,这是我理解的一个特征。如何在不从头开始实施的情况下获得IWICImagingFactory 的新实例。我看到一些关于名为 CoCreateInstance 的函数和一些 com API 细节的讨论,但这不是很清楚,因为我目前对 com API 的理解非常差。

【问题讨论】:

WIC API Overview 的示例代码解释了如何创建IWICImagingFactory 实例。您需要做的就是将其音译成 Rust 代码。 也就是说,windows 在处理 COM 方面已经明显优于 winapi,后者在一年多前收到了最后一次更新。 winapi-rs 没有太多未来。 【参考方案1】:

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

它产生一个正确类型的接口指针 (*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 的解决方案。

【讨论】:

【参考方案2】:

感谢评论中的建议,我通过查看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);

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

【讨论】:

以上是关于如何在winapi-rs中获取IWICImagingFactory的实例的主要内容,如果未能解决你的问题,请参考以下文章

如何在主函数中获取“语言代码”?

如何在快速路由器获取请求中从节点获取中使用获取

如何获取数组里对象的某个值

如何在对象中获取上下文?

如何在js代码中,如何获取event

在Postman中如何获取环境变量?