(Rust问题)C++双指针指向void的含义

我正在尝试通过遵循 Microsoft 为 ADSI API 和 Windows-RS 板条箱发布的 c++ 示例来使用 Rust 的活动目录。我不太明白这里发生了什么:

https://docs.microsoft.com/en-us/windows/win32/api/adshlp/nf-adshlp-adsopenobject

他们创建了一个指向 IAD 的未初始化指针(从我的 C# 知识中得出,它看起来像一个接口)然后,当需要使用它时,他们有一个双指针,它被强制转换为 void。我试图在 Rust 中复制这种行为,但我想我只是不明白发生了什么。这是我迄今为止尝试过的:

// bindings omitted
use windows::Interface;
use libc::c_void;
 
fn main() -> windows::Result<()> {
        let mut pads: *mut IADs = ptr::null_mut();
        let ppads: *mut *mut c_void = pads as _;

        unsafe {
            let _ = CoInitialize(ptr::null_mut());
            let mut ldap_root: Vec<u16> = "LDAP://rootDSE".encode_utf16().collect();
            let hr = ADsOpenObject(
                ldap_root.as_mut_ptr() as _,
                ptr::null_mut(),
                ptr::null_mut(),
                ADS_AUTHENTICATION_ENUM::ADS_SECURE_AUTHENTICATION.0 as _,
                & IADs::IID,
                ppads,
            );

            if !hr.is_err() {
                ...
            }

        }
   
    Ok(())
}

首先,我创建空指针可能是错误的,因为这不是他们在示例中所做的,但问题是 rust 不允许使用未初始化的变量,所以我不确定是什么相当于是。

其次,大概 pADs 变量是输出应该去的地方,但我不明白有一个指针,然后是一个双指针,指向一个没有所有者的对象的交互。即使这在 Rust 中是可能的,我也觉得这不是我应该做的。

第三,一旦我通过 FFI 调用更新了指针,我如何告诉 Rust 生成的输出类型是什么,以便我们可以用它做更多的工作?像 _ 那样做是行不通的,因为它是一个结构体,而且我觉得使用 transmute 是不好的

回答

FFI 中经常使用指针参数作为一种将数据与返回值本身一起返回的方法。这个想法是指针应该指向调用将用结果填充的某个现有对象。由于 Windows API 函数经常返回HRESULTs 来指示成功和失败,因此它们使用指针来返回其他内容。

在这种情况下,ADsOpenObject想要返回一个*void(请求的 ADs 接口对象),因此您需要给它一个指向现有*void对象的指针以供它填充:

let mut pads: *mut c_void = std::ptr::null_mut();
let ppads = &mut pads as *mut *mut c_void;

// or inferred inline

let hr = ADsOpenObject(
    ...
    &mut pads as _,
);

我更改pads*mut c_void简化此演示并匹配ADsOpenObject参数。成功调用后,您可以投射pads到您需要的任何内容。

主要区别在于强制转换pads&mut pads. 您之前所做的是创建ppads与 相同的值pads,从而告诉函数*void结果应该写在null. 不好。这使得参数pads代替。

并且未初始化与null差异是相当没有实际意义的,因为该函数的目标是无论如何都要覆盖它。


以上是(Rust问题)C++双指针指向void的含义的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>