如何从 Rust 正确调用需要 i8 缓冲区的 WinAPI 函数?

问题描述 投票:0回答:1

(使用winapi crate)

在没有示例的情况下,我很难弄清楚如何在 Rust 中使用 WinAPI 函数。我觉得我几乎拥有它......但在将 WinAPI 类型转换为我的 Rust 类型时遇到一些问题。我不太确定我应该如何确定它。

我正在尝试调用 GetGeoInfoA 函数(超链接到微软文档)。

这是我当前的代码尝试:

unsafe {
    let mut geo_data: Vec<i8> = Vec::new();
    let result =  GetGeoInfoA(2, 0, &mut geo_data[0], geo_data.len().try_into().unwrap(), 0);
    println!("GEO RESULT: {:#?}", String::from_utf8(mem::transmute(&geo_data[..result as usize])).unwrap());
    };

尽管我得到: “不能在不同大小的类型或大小相关的类型之间转换 源类型:

&[i8]
(128 位) 目标类型:
Vec<u8>
(192 位)”

...这,我相当期待。但我觉得我处理这个问题的方法都是错误的。

例如,我如何知道从哪里获取函数在其第二个参数中调用的“GeoType”?它要求使用 u32,所以我猜测不同的选项是通过索引进行索引和选择的?我在哪里可以找到这些信息?

归根结底,我需要弄清楚如何让 GetGeoInfoA 函数正常工作,尽管非常感谢任何额外的提示!

windows winapi rust
1个回答
0
投票

您的代码有多个问题:

  • 不要做
    &mut geo_data[0]
    。这是一个旧的 C++ 模式,甚至在 C++ 中它也已被弃用。请使用
    geo_data.as_mut_ptr()
    来代替。
  • 不要只是为了修复问题而扔掉
    transmute
    -
    transmute
    可能会破坏很多东西,应该非常小心地使用,并且只有在使用它的人绝对理解它的作用的情况下。就您而言,这不仅无效,而且是错误且危险的。
  • 在尝试将
    Vec
    转换为
    String
    时,您正在混淆拥有的向量和切片。如果您获取子切片(通过
    &geo_data[..result as usize]
    ),则无法将其转换为
    String
    ,因为它不拥有数据。当然,您可以从中创建一个
    &str
    。但如果您想调整
    Vec
    的大小,请使用
    .resize()
  • 您需要实际创建一些可以接收数据的缓冲区;您创建的
    Vec
    是空的。用一些零填充它。
  • 你的函数参数不正确,会返回
    0
    ,表示错误。
  • 您的
    Vec
    的类型为
    i8
    ,而
    String
    则需要
    u8
    。由于这两种类型是二进制兼容的,因此您可以将
    Vec
    更改为
    Vec<u8>
    并将指向它的指针转换为
    i8
    指针。

解决了所有这些问题后,这里是一些工作代码:

use winapi::um::errhandlingapi::GetLastError;
use winapi::um::winnls::GetGeoInfoA;

fn main() {
    let mut geo_data = vec![0u8; 10];

    let result = unsafe {
        GetGeoInfoA(
            2,
            6,
            geo_data.as_mut_ptr().cast(),
            geo_data.len().try_into().unwrap(),
            0,
        )
    };

    if result == 0 {
        let err = unsafe { GetLastError() };
        println!("Query failed with error: {}", err);
    } else {
        // Cut off the excess data
        geo_data.resize(result as usize, 0);
        println!("GEO RESULT: {}", String::from_utf8(geo_data).unwrap());
    }
}
GEO RESULT: de-ag
© www.soinside.com 2019 - 2024. All rights reserved.