Rust bindgen无法找到平台特定的库?

如何解决Rust bindgen无法找到平台特定的库?

我试图将我的简单应用程序从C移植到Rust。它仅在Mac上运行,仅在Mac上具有库。这是C代码中失败部分的简化版本

// myLog.h
#include <os/log.h> // macOS header

void debug(const char *str);

//************************************

// myLog.c
#include "myLog.h"

void debug(const char* str) {
    // call the macOS log function
    os_log_debug(OS_LOG_DEFAULT,"%{public}s",str);
}

只需调用gcc debug.c即可编译此代码,并且效果很好。

然后我将.h和.c添加到我的rust项目中,并指定如下所示的bindgen

fn main() {
    println!("cargo:rerun-if-changed=myLog.h");

    let bindings = bindgen::Builder::default()
        .header("myLog.h")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .generate()
        .expect("Unable to build bindgen");
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("mylog_bindings.rs"))
        .expect("Couldn't write bindings!");
}

并且main函数没有其他功能,但是现在测试日志:

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

use std::ffi::CString;
include!(concat!(env!("OUT_DIR"),"/mylog_bindings.rs"));

fn main() {
    let log_infomation = CString::new("Log from Rust").expect("Failed to create c string");
    let c_pointer = log_infomation.as_ptr();
    unsafe {
        debug(c_pointer);
    }
}

程序失败,出现以下错误

error: linking with `cc` Failed: exit code: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "-L" ......
  = note: Undefined symbols for architecture x86_64:
            "_debug",referenced from:
                bindgen_test::main::hc0e5702b90adf92c in bindgen_test.3ccmhz8adio5obzw.rcgu.o
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command Failed with exit code 1 (use -v to see invocation)
          

error: aborting due to prevIoUs error; 2 warnings emitted

error: Could not compile `bindgen_test`.

我不确定为什么会失败,但是我发现如果删除整个不安全的块(不调用函数),编译将起作用。但是有人可以向我解释我做错了什么吗?我需要添加一些东西使其编译吗?

非常感谢您!

解决方法

问题是您没有在任何地方包括myLog.c文件,仅包括myLog.h标头。这就是bindgen的作用:它将C头文件转换为Rust代码,但不编译C代码本身。

为此,您需要cc条板箱。您必须在cc文件中同时使用bindgenbuild.rs

use std::env;
use std::path::PathBuf;

fn main() {
    println!("cargo:rerun-if-changed=myLog.h");
    println!("cargo:rerun-if-changed=myLog.c");  // new line here!!

    let bindings = bindgen::Builder::default()
        .header("myLog.h")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .generate()
        .expect("Unable to build bindgen");
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("mylog_bindings.rs"))
        .expect("Couldn't write bindings!");

    //Compile and link a static library named `myLog`:
    cc::Build::new()
        .file("myLog.c")
        .compile("myLog");
}

请不要忘记将cc板条箱添加到您的build-dependencies中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?