【问题标题】:"cannot find function" when trying to follow FFI example尝试遵循 FFI 示例时“找不到函数”
【发布时间】:2019-05-04 04:02:27
【问题描述】:

我正在尝试开始使用 Rust FFI,所以我去了the nomicon's documentation on FFI 并尝试复制“外部调用约定”示例。

我编写了一段简单的代码,只是复制粘贴示例并尝试使用声明的函数:

extern crate libc;

#[cfg(all(target_os = "win32", target_arch = "x86"))]
#[link(name = "kernel32")]
#[allow(non_snake_case)]
extern "stdcall" {
    fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int;
}

fn main() {
    println!("Enter main");
    unsafe {
        let ret = SetEnvironmentVariableA("SOME_NEW_ENV_VAR\0", "NEW_ENV_VAR_VAL\0");
        println!("ret: {}", ret);
    }
    println!("Exit main");
}

这并没有真正做任何有用的事情,我只是想看看我是否可以链接并调用一个函数而不会爆炸。

我从编译器得到这个错误:

error[E0425]: cannot find function `SetEnvironmentVariableA` in this scope
  --> src\main.rs:13:19
   |
13 |         let ret = SetEnvironmentVariableA("SOME_NEW_ENV_VAR\0","NEW_ENV_VAR_VAL\0");
   |                   ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

示例是否已过时?我错过了什么明显的东西吗?看来无论如何,我声明的SetEnvironmentVariableA 应该在范围内。

我知道 winapi crate,但我正在尝试学习 Rust FFI;使用解决问题的现有板条箱将无法达到目的。

【问题讨论】:

  • 你确定你在#[cfg(all(target_os = "win32", target_arch = "x86"))]上编译吗?
  • 我在 windows 上,所以 win32 和 x86 应该生成兼容的二进制文件。

标签: rust ffi


【解决方案1】:

Stargateur 的评论是正确的方向。删除以下行解决了问题:

#[cfg(all(target_os = "win32", target_arch = "x86"))]

cfg attribute 用于本教程的“外部调用约定”部分,所以我认为它是让链接和调用约定起作用的魔法的一部分。 cfg 根本不是这样工作的。仅文档的 URL 就解释了为什么我收到“找不到函数”错误:“条件编译”。

我能够将示例扩展为一种 hello world:

#[link(name = "kernel32")]
#[allow(non_snake_case)]
extern "stdcall" {
    fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> i32;
    fn GetEnvironmentVariableA(n: *const u8, v: *mut u8, s : u32) -> i32;
}

fn main() {
    println!("Enter main");
    unsafe {
        let ret = SetEnvironmentVariableA("HELLO_WORLD_VAR\0".as_ptr(),"hellow world!\0".as_ptr());
        println!("ret: {}", ret);
        let mut dummy : u8 = 0;
        let ret1 = GetEnvironmentVariableA("HELLO_WORLD_VAR\0".as_ptr(), &mut dummy, 0);
        println!("ret1: {}", ret1);
        if ret1 > 0 {
            let mut read = vec![0; ret1 as usize];
            let ret2 = GetEnvironmentVariableA("HELLO_WORLD_VAR\0".as_ptr(),read.as_mut_ptr(), ret1 as u32);
            let read_str = String::from_utf8(read).unwrap();
            println!("ret2: {}", ret2);
            println!("read_str: {}", read_str);
            println!("read_str.len(): {}", read_str.len());
        }
    }
    println!("Exit main");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-13
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 2019-11-19
    • 2011-03-12
    • 1970-01-01
    相关资源
    最近更新 更多