如何解决(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\0".encode_utf16().collect();
let hr = ADsOpenObject(
ldap_root.as_mut_ptr() as _,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 函数通常返回 HRESULT
以指示成功和失败,因此它们使用指针来返回其他内容。
在这种情况下,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
的区别相当没有实际意义,因为该函数的目标是无论如何都要覆盖它。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。