使用旧的 Rust 2015
0.2.0 |
|
---|---|
0.1.1 |
|
0.1.0 |
|
#62 在 #haskell
18KB
261 行
Curryrs
Curryrs(Haskell Curry 的名字游戏,rs 代表 Rust 库,其发音为 couriers)是一个库,用于提供 Rust 和 Haskell 代码之间易于使用的绑定。鉴于两种语言都固有的类型安全,Curryrs 通过提供两个语言之间的接口来弥合两种语言之间的差距,使得编写 FFI 代码成为一种相对无痛的体验。
此库仅在 GHC 8.0.1 和 Rust Stable 上进行了测试。要运行测试套件,您需要 gcc。
安装
在您的 Rust 项目中 Cargo.toml
[dependencies]
curryrs = "^0.2.0"
在您的 Haskell 项目中它的 cabal 文件
build-depends: curryrs >= 0.2.0 < 0.3.0
如何使用 Curryrs
每个库都包含一个用于 FFI 类型的模块和一个用于转换的模块,该模块需要执行额外的工作。目前,此转换模块仅影响布尔类型,但未来此模块的工作可能包括结构体和其他更复杂的数据结构。
Rust 中的 Haskell
如果您想从 Rust 创建导出到 Haskell 的函数,请执行以下操作
#[macro_use]
extern crate curryrs;
use curryrs::types::*;
// Place each function you want exported into the safe_ffi! macro and it will
// export each one and place the pub extern for you!
safe_ffi! (
fn double(x: I32) -> I32 {
2 * x
}
fn square(x: U64) -> U64 {
x * x
}
fn cube(x: I64) -> I64 {
x * x * x
}
);
目前,当 unsafe 作为 fn
标题的一部分时,此宏不起作用。有两个宏:safe_ffi!
和 unsafe_ffi!
。虽然它们目前相同,但当创建用于自动生成绑定的二进制文件时,它将根据函数中使用的宏创建安全或不安全的导入到 Haskell。推荐的使用情况是 safe_ffi!
用于您所需的大部分内容。
然后在您的 Haskell 程序中
import Curryrs.Types
foreign import ccall "double" double :: I64 -> I64
foreign import ccall "square" square :: I64 -> I64
foreign import ccall "cube" cube :: I64 -> I64
quadruple :: I64 -> I64
quadruple x = double $ double x
fourthPower :: I64 -> I64
fourthPower x = square $ square x
ninthPower :: I64 -> I64
ninthPower x = cube $ cube x
Rust 中的 Haskell
要在 Rust 中运行您的 Haskell 代码,请按照以下步骤操作
首先编写和导出您想要用于 Haskell 的代码,并使用 Curryrs.Types 模块来拥有 FFI 兼容的类型。
import Curryrs.Types
foreign export ccall fourth :: I64 -> I64
foreign export ccall fifth :: I64 -> I64
foreign export ccall sixth :: I64 -> I64
fourth :: I64 -> I64
fourth x = x * x * x * x
fifth :: I64 -> I64
fithh x = x * x * x * x * x
sixth :: I64 -> I64
sixth x = x * x * x * x * x * x
在您的 cabal 文件中添加以下行
other-extensions: ForeignFunctionInterface
-- It should end with .so if you're on Linux, .dylib for Mac, and
-- .dll for Windows
ghc-options: -dynamic -fPIC -shared -o lib{your_library_name_here}.so
现在在您的 Cargo.toml 文件中,在 package 下添加以下内容
build = "build.rs"
然后在您的 build.rs
文件中
fn main() {
println!("cargo:rustc-link-search=native={path_to_your_haskell_library_directory}");
println!("cargo:rustc-link-lib=native={library_name_w/o_lib_and_extension}");
}
这将在编译时链接您的 Haskell 库。现在让我们看看实际的代码
extern crate curryrs;
use curryrs::hsrt::{start,stop};
use curryrs::types::I64;
extern {
pub fn fourth(x: I64) -> I64;
pub fn fifth(x: I64) -> I64;
pub fn sixth(x: I64) -> I64;
}
fn main() {
// Input is whatever you want to pass to argv whenever
// you start the Haskell Runtime. You need to start it
// or calls to Haskell code will fail.
start("Haskell Functions".to_string());
println!("2^4 is: {}", unsafe{fourth(2)});
println!("2^5 is: {}", unsafe{fifth(2)});
println!("2^6 is: {}", unsafe{sixth(2)});
// You need to make sure the runtime is stopped
// otherwise you'll have undefined behavior
// and wasted resources.
stop();
}
这使得在没有需要处理正确链接库的情况下完成此操作变得容易,并且您可以轻松地调用所需的运行时。
该库还允许您选择要使用的 Haskell 运行时版本。默认情况下,它使用非线程版本。您可以使用 Cargo.toml
中的功能标志来选择您想要使用哪个。
[dependencies]
# If you need the threaded runtime put this:
curryrs = { version = "^0.2.0", features = "threaded" }
# If you need the threaded runtime w/ logging put this:
curryrs = { version = "^0.2.0", features = "threaded_l" }
# If you need the threaded runtime w/ debug output put this:
curryrs = { version = "^0.2.0", features = "threaded_debug" }
错误报告
如果您遇到任何类型的错误,请首先查看问题跟踪器。如果您的错误已经存在或以前已关闭,请查看如何解决该错误或通过解释在使用库时发生了什么来为打开的错误贡献力量。重复的错误将被标记并关闭。
贡献
请参阅CONTRIBUTING.md获取更多信息。
许可证
许可方式为以下之一
- Apache License, Version 2.0,(LICENSE-APACHE或http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或http://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确声明,否则您提交的任何贡献,根据Apache-2.0许可证的定义,将双重许可,如上所述,不附加任何额外条款或条件。