added rust support (#50)

* added rust support

* move binding files to their respective directories

* updated README.md

* updated pypi ci package-dir

* add ruapu::rua() for rust
This commit is contained in:
Cocoa 2024-02-28 23:34:26 +08:00 committed by GitHub
parent 8d3ffb0e60
commit 550a9caa0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 214 additions and 5 deletions

View File

@ -35,8 +35,16 @@ jobs:
run: |
python3 -m pip install pip -U
python3 -m pip install setuptools -U
cd python
pip3 install .
python3 -c 'import ruapu; print(ruapu.supports("neon")); print(ruapu.supports(isa="avx"))'
- name: build-test-rust
run: |
rustup update stable
rustup default stable
cd rust
cargo build --verbose
cargo test --verbose
macos:
runs-on: macos-latest
@ -50,8 +58,16 @@ jobs:
run: |
python3 -m pip install pip -U
python3 -m pip install setuptools -U
cd python
pip3 install .
python3 -c 'import ruapu; print(ruapu.supports("neon")); print(ruapu.supports(isa="avx"))'
- name: build-test-rust
run: |
rustup update stable
rustup default stable
cd rust
cargo build --verbose
cargo test --verbose
macos-arm64:
runs-on: macos-14
@ -65,8 +81,16 @@ jobs:
run: |
python3 -m pip install pip -U
python3 -m pip install setuptools -U
cd python
pip3 install .
python3 -c 'import ruapu; print(ruapu.supports("neon")); print(ruapu.supports(isa="avx"))'
- name: build-test-rust
run: |
rustup update stable
rustup default stable
cd rust
cargo build --verbose
cargo test --verbose
windows:
runs-on: windows-latest
@ -86,8 +110,16 @@ jobs:
run: |
python3 -m pip install pip -U
python3 -m pip install setuptools -U
cd python
pip3 install .
python3 -c 'import ruapu; print(ruapu.supports("neon")); print(ruapu.supports(isa="avx"))'
- name: build-test-rust
run: |
rustup update stable
rustup default stable
cd rust
cargo build --verbose
cargo test --verbose
qemu:
runs-on: ubuntu-latest

View File

@ -31,6 +31,7 @@ jobs:
CIBW_BUILD: "cp311*"
CIBW_BUILD_VERBOSITY: 1
with:
package-dir: python
output-dir: wheelhouse
- uses: actions/upload-artifact@v4

3
.gitignore vendored
View File

@ -3,3 +3,6 @@ build/
dist/
*.egg-info/
*.pyc
# Rust files
target

View File

@ -102,7 +102,7 @@ pip3 install ruapu
```shell
# from source code
pip3 install .
pip3 install ./python
```
</td>
<td>
@ -121,6 +121,36 @@ ruapu.supports(isa="avx2")
</td></tr>
</table>
### ruapu with Rust
<table>
<tr><td>
Compile ruapu library
```shell
# from source code
cd rust
cargo build --release
```
</td>
<td>
Use ruapu in Rust
```rust
extern crate ruapu;
fn main() {
println!("supports neon: {}", ruapu::supports("neon").unwrap());
println!("supports avx2: {}", ruapu::supports("avx2").unwrap());
println!("rua: {:?}", ruapu::rua());
}
```
</td></tr>
</table>
<details>
<summary>Github-hosted runner result (Linux)</summary>

View File

@ -1,9 +1,9 @@
#define RUAPU_IMPLEMENTATION
#include "../ruapu.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#define RUAPU_IMPLEMENTATION
#include "ruapu.h"
static PyObject *ruapu_supports_py(PyObject *self, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = {"isa", NULL};

View File

@ -16,7 +16,7 @@ class bdist_wheel_abi3(bdist_wheel):
ext = Extension(
name = 'ruapu',
sources = ['ruapu-py.c'],
sources = ['ruapu-binding.c'],
py_limited_api = True
)

39
rust/Cargo.lock generated Normal file
View File

@ -0,0 +1,39 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "cc"
version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
[[package]]
name = "claim"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81099d6bb72e1df6d50bb2347224b666a670912bb7f06dbe867a4a070ab3ce8"
dependencies = [
"autocfg",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "ruapu"
version = "0.1.0"
dependencies = [
"cc",
"claim",
"lazy_static",
]

13
rust/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "ruapu"
version = "0.1.0"
edition = "2021"
[build-dependencies]
cc = "1.0"
[dev-dependencies]
claim = "0"
[dependencies]
lazy_static = "1"

6
rust/build.rs Normal file
View File

@ -0,0 +1,6 @@
fn main() {
cc::Build::new()
.file("src/ruapu-binding.c")
.compile("ruapu-rs");
println!("cargo:rerun-if-changed=ruapu-binding.c");
}

7
rust/examples/ruapu.rs Normal file
View File

@ -0,0 +1,7 @@
extern crate ruapu;
fn main() {
println!("supports neon: {}", ruapu::supports("neon").unwrap());
println!("supports avx2: {}", ruapu::supports("avx2").unwrap());
println!("rua: {:?}", ruapu::rua());
}

76
rust/src/lib.rs Normal file
View File

@ -0,0 +1,76 @@
#[macro_use]
extern crate lazy_static;
use std::ffi::{CString, CStr, NulError};
use std::os::raw::c_char;
use std::sync::Mutex;
use std::result::Result;
lazy_static! {
static ref RUAPU_INITILIASED: Mutex<bool> = Mutex::new(false);
}
extern "C" {
fn ruapu_init();
fn ruapu_supports(isa: *const c_char) -> i32;
fn ruapu_rua() -> *const *const c_char;
}
fn init_ruapu() {
if !*(RUAPU_INITILIASED.lock().unwrap()) {
unsafe {
ruapu_init();
}
*(RUAPU_INITILIASED.lock().unwrap()) = true;
}
}
pub fn supports(isa: &str) -> Result<bool, NulError> {
init_ruapu();
let isa = CString::new(isa)?;
let isa_ptr = isa.as_ptr();
unsafe {
Ok(ruapu_supports(isa_ptr) != 0)
}
}
pub fn rua() -> Vec<String> {
init_ruapu();
let mut result = Vec::new();
unsafe {
let mut i = 0;
let ptr = ruapu_rua();
loop {
let ptr = ptr.offset(i);
if *ptr == std::ptr::null() {
break;
}
let c_str = CStr::from_ptr(*ptr);
let str = c_str.to_str().unwrap();
result.push(str.to_string());
i += 1;
}
}
return result;
}
#[cfg(test)]
mod tests {
use super::*;
use claim::assert_ok;
#[test]
fn test_supports() {
assert_ok!(supports("avx2"));
assert_ok!(supports("non_exists_feature"));
assert_eq!(supports("non_exists_feature").unwrap(), false);
let supported_features = rua();
for feature in supported_features {
assert_eq!(supports(&feature).unwrap(), true);
}
let nul_error = supports("neon\0avx2").unwrap_err();
assert_eq!(nul_error.into_vec(), b"neon\0avx2");
}
}

2
rust/src/ruapu-binding.c Normal file
View File

@ -0,0 +1,2 @@
#define RUAPU_IMPLEMENTATION
#include "../../ruapu.h"