将R对象传递给Rust程序需要哪些步骤?
R和Rust都可以与C代码接口,所以我认为这是非常可能的。然而,我有点不清楚如何进行 我已经阅读了这些章节,寻找答案: 但是,虽然我精通将R对象传递给Rust程序需要哪些步骤?,r,rust,R,Rust,R和Rust都可以与C代码接口,所以我认为这是非常可能的。然而,我有点不清楚如何进行 我已经阅读了这些章节,寻找答案: 但是,虽然我精通R,但我不是一个系统程序员,我对这种努力的构建链是什么样子感到困惑 使用Rinternals.h将是理想的,但我也会选择更简单的.C接口。如果R可以与C代码接口,那么从暴露C风格函数的Rust代码编译共享库根本没有问题 你可以很容易地使用你的库,因为它是用C或C++编写的。当然,您将无法直接从R中使用Rust对象和库,您必须创建适当的C接口来转换它们的函数
R
,但我不是一个系统程序员,我对这种努力的构建链是什么样子感到困惑
使用
Rinternals.h
将是理想的,但我也会选择更简单的.C
接口。如果R可以与C代码接口,那么从暴露C风格函数的Rust代码编译共享库根本没有问题
<>你可以很容易地使用你的库,因为它是用C或C++编写的。当然,您将无法直接从R中使用Rust对象和库,您必须创建适当的C接口来转换它们的函数
以下是我如何为SBCL做到这一点,我想这与R非常相似:
生锈的一面
一些代码:
%cat实验.rs
extern crate libc;
use libc::{c_int, c_char};
use std::{ffi, str};
#[no_mangle]
pub extern fn rust_code_string_to_int(s: *const c_char, r: *mut c_int) -> c_int {
let string = String::from_utf8_lossy(unsafe { ffi::CStr::from_ptr(s).to_bytes() });
match <isize as str::FromStr>::from_str(&*string) {
Ok(value) => { unsafe { *r = value as c_int }; 0 },
Err(_) => -1,
}
}
接下来,在SBCL侧
现在我正在加载我的共享库,然后我可以访问我的rust\u code\u string\u to\u int
函数:
RUST> (sb-alien:load-shared-object "libexperiment.dylib")
#P"libexperiment.dylib"
RUST> (sb-alien:with-alien ((result sb-alien:int 0))
(values (sb-alien:alien-funcall (sb-alien:extern-alien "rust_code_string_to_int"
(sb-alien:function sb-alien:int
(sb-alien:c-string :external-format :utf-8)
(sb-alien:* sb-alien:int)))
(sb-alien:make-alien-string "42")
(sb-alien:addr result))
result))
0
42
我也为此奋斗了一段时间,但一旦你知道我其实并不难 首先按照以下说明创建锈蚀库:。 下面是一个示例库:
//src/lib.rs
#[no_mangle]
pub fn kelvin_to_fahrenheit(n: f64) -> f64 {
n * 9.0/5.0 - 459.67
}
如果按照中的说明操作,则应能够生成*.so
(或*.dll
或.dylib
,具体取决于您的系统)。我们假设这个编译后的文件名为libtempr.so
现在创建一个C++文件,它将传递您需要的函数:r:< /p>
//embed.cpp
extern "C" {
double kelvin_to_fahrenheit(double);
}
// [[Rcpp::export]]
double cpp_kelvin_to_fahrenheit(double k) {
double f = kelvin_to_fahrenheit(k);
return(f);
}
现在,在启动R之前,请确保环境变量LD_LIBRARY_PATH
包含存储先前生成的共享对象(libtempr.so
)的目录。在shell中,请执行以下操作:
$ export LD_LIBRARY_PATH=/home/sam/path/to/shared/object:$LD_LIBRARY_PATH
$ rstudio # I highly recommend using Rstudio for your R coding
最后,在Rstudo中,编写以下文件:
library(Rcpp)
Sys.setenv("PKG_LIBS"="-L/home/sam/path/to/shared/object -ltempr")
sourceCpp("/home/sam/path/to/embed.cpp", verbose = T, rebuild = T)
cpp_kelvin_to_fahrenheit(300)
- 请注意,在
中,Sys.setenv
选项指向包含共享对象的目录-L
- 还要注意,
选项是共享对象的名称,不带-l
前缀,也不带lib
。因此
(或系统上的任何后缀)
- 在R中使用
设置Sys.setenv
变量不起作用。在启动R之前导出变量LD_LIBRARY_路径
<>代码> VBOSOSE < /Cord>选项,这样您就可以看到编译Rcpp的C++文件<代码> > >代码>。请注意,在<代码> pkgyLIbs>代码>中,如何使用这些选项来编译C++文件。
<>代码>重建//COD>选项,强制每次运行R代码行时强制重建C++文件。
80.33
如果有什么不清楚的地方,请在评论中提问,我会努力改进我的答案
希望有帮助:)
最后请注意,基本函数
dyn.load
和.C
可用作替代方法。但这需要编写比这种方法多得多的样板包装代码。可能有用-您想从Rust调用R,还是从R调用Rust?如果您选择后者,请查看.Call()
而不是.C()
,这是任何人都不应该再使用的。RCPP可以帮助您使用一个中间层。我想从R中调用RIST代码,并在我的R会话中使用对象上的锈库。您应该能够(很容易)通过Rcpp从R到C++。在这一点上,@swizard的答案就可以使用了。如果您感兴趣,我们可以制作一个小演示,作为中的一个示例,例如。
library(Rcpp)
Sys.setenv("PKG_LIBS"="-L/home/sam/path/to/shared/object -ltempr")
sourceCpp("/home/sam/path/to/embed.cpp", verbose = T, rebuild = T)
cpp_kelvin_to_fahrenheit(300)