如何在 Rust winapi 编程中使用 COM VARIANT? [英] How to use a COM VARIANT in Rust winapi programming?

查看:21
本文介绍了如何在 Rust winapi 编程中使用 COM VARIANT?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试转换 C++ COM 代码TaskScheduler 转为 Rust 并坚持使用 ITaskService::ConnectVARIANT 参数:

I'm trying to convert the C++ COM code for TaskScheduler to Rust and am stuck with the VARIANT argument of ITaskService::Connect:

extern crate winapi;
use winapi::{
    ctypes::c_void,
    shared::{
        guiddef::{GUID, REFCLSID, REFIID},
        ntdef::{HRESULT, NULL},
        rpcdce::{RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE},
        winerror::FAILED,
        wtypes::VARENUM,
        wtypesbase::CLSCTX_INPROC_SERVER,
    },
    um::{
        combaseapi::{CoCreateInstance, CoInitializeEx, CoInitializeSecurity, CoUninitialize},
        oaidl,
        objbase::COINIT_MULTITHREADED,
        taskschd::{ITaskService, TaskScheduler},
    },
    Class, Interface,
}; // 0.3.7

fn main() {
    //  Create an instance of the Task Service.
    let mut p_service: *mut ITaskService = unsafe { std::mem::zeroed() };

    let hr = unsafe {
        CoCreateInstance(
            &TaskScheduler::uuidof(),
            std::ptr::null_mut(),
            CLSCTX_INPROC_SERVER,
            &ITaskService::uuidof(),
            &mut p_service as *mut *mut ITaskService as *mut *mut c_void,
        )
    };

    // [...]
    // //  Connect to the task service.
    // let hr = pService->Connect(_variant_t(), _variant_t(),
    //     _variant_t(), _variant_t());

    let hr = unsafe {
        (&mut *p_service).Connect(
            oaidl::VARIANT { /* VT_EMPTY HERE */ },
            oaidl::VARIANT { /* VT_EMPTY HERE */ },
            oaidl::VARIANT { /* VT_EMPTY HERE */ },
            oaidl::VARIANT { /* VT_EMPTY HERE */ },
        )
    };
}

文档说:

_variant_t( ) 构造一个空的 _variant_t 对象,VT_EMPTY.

我发现没有提及如何使用自述文件中所述的变体:

I found no mention on how to use the variant as stated in the README:

使用 std::mem::zeroed() 创建联合的实例,然后使用其中一种变体方法分配您想要的值.

Use std::mem::zeroed() to create an instance of the union, and then assign the value you want using one of the variant methods.

检查文档中的variant"时,列表中没有 _variant_t fn,所以不确定它在 Rust 中的名称

When checking the docs for "variant", there's no _variant_t fn on the list, so not sure what it is called in Rust

错误

field `0` of struct `winapi::um::oaidl::VARIANT_n1` is private

field `0` is private

为了

  oaidl::VARIANT {
    n1: oaidl::VARIANT_n1 {
      0: [0, 0, 0]
    }
  }

推荐答案

初始化联合在 winapi 的自述文件:

Initializing unions is explained in winapi's README:

使用 std::mem::zeroed() 创建联合的实例,然后使用其中一种变体方法分配您想要的值.

How do I create an instance of a union?

Use std::mem::zeroed() to create an instance of the union, and then assign the value you want using one of the variant methods.

例如,对于VARIANT_n1,方法有n2n2_mutdecValdecVal_mut.您自然需要使用 _mut 方法来赋值.

For instance, for VARIANT_n1, the methods are n2, n2_mut, decVal and decVal_mut. You will naturally need to use a _mut method to assign a value.

请注意,从 winapi 0.3.7 开始,您还可以使用 Default::default() 来获取归零联合,而不是使用不安全的 std::mem::zeroed().您需要在 winapi crate 上启用 impl-default 功能以实现 Default trait.

Note that, starting with winapi 0.3.7, you can also use Default::default() to obtain a zeroed union instead of using the unsafe std::mem::zeroed(). You need to enable the impl-default feature on the winapi crate for the Default trait to be implemented.

这篇关于如何在 Rust winapi 编程中使用 COM VARIANT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆