Add Rust Wrapper (#1977)

* Add Rust Wrapper

Signed-off-by: Steffen Golle <somnium@stampernet.de>

* Remove Rust Wrapper

Signed-off-by: Steffen Golle <somnium@stampernet.de>

* Add Rust Wrapper as submodule

Signed-off-by: Steffen Golle <somnium@stampernet.de>

* Add Rust Wrapper as submodule

Signed-off-by: Steffen Golle <somnium@stampernet.de>

* Remove Rust wrapper submodule

* Readd Rust wrapper version 0.2.0
This commit is contained in:
Steffen Golle
2021-02-27 18:08:28 +01:00
committed by GitHub
parent 5674475f43
commit cdc1eccc87
8 changed files with 261 additions and 0 deletions

3
wrappers/Rust/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/target
Cargo.lock
/.vscode

22
wrappers/Rust/Cargo.toml Normal file
View File

@@ -0,0 +1,22 @@
[package]
name = "coolprop-rs"
version = "0.2.0"
authors = ["Steffen Golle <somnium@stampernet.de>"]
license = "MIT"
readme = "README.md"
repository = "https://github.com/sgolle/coolprop-rs"
documentation = "https://github.com/sgolle/coolprop-rs"
homepage = "https://crates.io/crates/coolprop-rs"
description = """
Coolprop Wrapper for Rust
"""
keywords = ["coolprop", "wrapper"]
categories = ["api-bindings", "external-ffi-bindings"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
bindgen = "0.55"

21
wrappers/Rust/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Steffen Golle
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

51
wrappers/Rust/README.md Normal file
View File

@@ -0,0 +1,51 @@
# Welcome to coolprop-rs
**EXPERIMENTAL** CoolProp Wrapper for Rust
The wrapper uses rust-bindgen to create the bindings to the C++ shared library of CoolProp and adds some wrapper functions. The wrapper should work on all platforms that CoolProp and Rust work on.
## Prerequisites
The CoolProp shared library (_libCoolProp.so_) and header file (_CoolPropLib.h_) must be installed on the computer in the systems folder. On Linux e. g. _/usr/lib64_ and _/usr/include_. Instructions to compile and install CoolProp for your system can be found on the project page of [CoolProp](https://github.com/CoolProp/CoolProp).
## Installation
The wrapper gets published on [crates.io](https://crates.io/crates/coolprop-rs) as `coolplot-rs` and you can add the library in your project.
```toml
[dependencies]
coolprop-rs = "0.2"
```
## Examples
At the moment the wrapper provides access to either the full C++ bindings directly or a small subset of methods which utilizes Rust types, error handling and unit testing.
The C++ bindings can be used with:
Rust:
```Rust
use coolprop-rs::bindings::*;
```
The subset of Rust methods are at the moment **PropsSI()** and **HAPropsSI()**:
Rust:
```Rust
use coolprop-rs;
println!("{:?}", coolprop-rs::PropsSI("H", "T", 300.0, "Q", 1.0, "R134a").unwrap());
println!("{:?}", coolprop-rs::HAPropsSI("H", "T", 300.0, "P", 100000.0, "R", 0.0).unwrap());
```
Output:
```bash
413265.6843372975
27013.112479771713
```
## License
This Rust package is released under the terms of the MIT license.

34
wrappers/Rust/build.rs Normal file
View File

@@ -0,0 +1,34 @@
extern crate bindgen;
use std::env;
use std::path::PathBuf;
fn main() {
// Tell cargo to tell rustc to link the system bzip2
// shared library.
println!("cargo:rustc-link-lib=CoolProp");
// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed=wrapper.h");
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header("wrapper.h")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}

View File

@@ -0,0 +1,6 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

122
wrappers/Rust/src/lib.rs Normal file
View File

@@ -0,0 +1,122 @@
use std::error;
use std::fmt;
use std::panic;
pub mod bindings;
// macro_rules! c_str {
// ($s:expr) => {{
// concat!($s, "\0").as_ptr() as *const i8
// }};
// }
#[derive(Debug)]
pub struct CoolPropError;
impl error::Error for CoolPropError {
// fn description(&self) -> &str {
// // Both underlying errors already impl `Error`, so we defer to their
// // implementations.
// match *self {
// // Normally we can just write `err.description()`, but the error
// // type has a concrete method called `description`, which conflicts
// // with the trait method. For now, we must explicitly call
// // `description` through the `Error` trait.
// CoolPropError::Parse(ref err) => error::Error::description(err),
// }
// }
// fn cause(&self) -> Option<&error::Error> {
// match *self {
// // N.B. Both of these implicitly cast `err` from their concrete
// // types (either `&io::Error` or `&num::ParseIntError`)
// // to a trait object `&Error`. This works because both error types
// // implement `Error`.
// CoolPropError::Parse(ref err) => Some(err),
// }
// }
}
impl fmt::Display for CoolPropError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
// Underlying errors already impl `Display`, so we defer to
// their implementations.
CoolPropError => write!(f, "CoolProp error: {}", CoolPropError),
}
}
}
#[allow(non_snake_case)]
pub fn PropsSI(
output: &str,
name1: &str,
prop1: f64,
name2: &str,
prop2: f64,
refr: &str,
) -> Result<f64, CoolPropError> {
let result = panic::catch_unwind(|| unsafe {
bindings::PropsSI(
format!("{}{}", output, "\0").as_ptr() as *const i8,
format!("{}{}", name1, "\0").as_ptr() as *const i8,
prop1,
format!("{}{}", name2, "\0").as_ptr() as *const i8,
prop2,
format!("{}{}", refr, "\0").as_ptr() as *const i8,
)
});
match result {
Ok(result) => Ok(result),
Err(_) => Err(CoolPropError),
}
}
#[allow(non_snake_case)]
pub fn HAPropsSI(
output: &str,
name1: &str,
prop1: f64,
name2: &str,
prop2: f64,
name3: &str,
prop3: f64,
) -> Result<f64, CoolPropError> {
let result = panic::catch_unwind(|| unsafe {
bindings::HAPropsSI(
format!("{}{}", output, "\0").as_ptr() as *const i8,
format!("{}{}", name1, "\0").as_ptr() as *const i8,
prop1,
format!("{}{}", name2, "\0").as_ptr() as *const i8,
prop2,
format!("{}{}", name3, "\0").as_ptr() as *const i8,
prop3,
)
});
match result {
Ok(result) => Ok(result),
Err(_) => Err(CoolPropError),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_high_level_interface() {
assert_eq!(
PropsSI("H", "T", 300.0, "Q", 1.0, "R134a").unwrap(),
413265.6843372975
);
assert_eq!(
HAPropsSI("H", "T", 300.0, "P", 100000.0, "R", 0.0).unwrap(),
27013.112479771713
);
}
// #[test]
// fn test_low_level_interface() {
// let mut state = bindings::AbstractState("HEOS", "Water")
// }
}

2
wrappers/Rust/wrapper.h Normal file
View File

@@ -0,0 +1,2 @@
#include "stdbool.h"
#include "CoolPropLib.h"