Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将R对象传递给Rust程序需要哪些步骤?_R_Rust - Fatal编程技术网

将R对象传递给Rust程序需要哪些步骤?

将R对象传递给Rust程序需要哪些步骤?,r,rust,R,Rust,R和Rust都可以与C代码接口,所以我认为这是非常可能的。然而,我有点不清楚如何进行 我已经阅读了这些章节,寻找答案: 但是,虽然我精通R,但我不是一个系统程序员,我对这种努力的构建链是什么样子感到困惑 使用Rinternals.h将是理想的,但我也会选择更简单的.C接口。如果R可以与C代码接口,那么从暴露C风格函数的Rust代码编译共享库根本没有问题 你可以很容易地使用你的库,因为它是用C或C++编写的。当然,您将无法直接从R中使用Rust对象和库,您必须创建适当的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
      设置
      LD_LIBRARY_路径
      变量不起作用。在启动R之前导出变量
    • <>代码> VBOSOSE < /Cord>选项,这样您就可以看到编译Rcpp的C++文件<代码> > >代码>。请注意,在<代码> pkgyLIbs>代码>中,如何使用这些选项来编译C++文件。 <>代码>重建//COD>选项,强制每次运行R代码行时强制重建C++文件。
    如果你做得很好,那么在交互式控制台中运行上面的R文件,当你到达最后一行时,它应该输出
    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)