Rust bindgen 找不到特定于平台的库?
Rust bindgen cannot find platform specific library?
我正在尝试将我的简单应用程序从 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
header。这就是 bindgen
所做的:它将 C header 文件转换为 Rust 代码,但它并不编译 C 代码本身。
为此你需要 cc
箱子。您必须在 build.rs
文件中同时使用 cc
和 bindgen
:
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
。
我正在尝试将我的简单应用程序从 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
header。这就是 bindgen
所做的:它将 C header 文件转换为 Rust 代码,但它并不编译 C 代码本身。
为此你需要 cc
箱子。您必须在 build.rs
文件中同时使用 cc
和 bindgen
:
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
。