Working python arg and return
This commit is contained in:
Generated
+96
@@ -2,6 +2,102 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpython"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43b398a2c65baaf5892f10bb69b52508bf7a993380cc4ecd3785aaebb5c79389"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
"python3-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flux-rt"
|
name = "flux-rt"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cpython",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.175"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python3-sys"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f53ef6740367a09718d2cd21ba15b0d7972342a38e554736bcee7773e45c9f5"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,6 @@
|
|||||||
name = "flux-rt"
|
name = "flux-rt"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
cpython = "0.7.2"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
def hello(name: str) -> str:
|
def hello(name):
|
||||||
print("Hello, bro! " + name)
|
print("Hello, bro! " + name)
|
||||||
return "Idk, return value i guess"
|
return "Idk, return value i guess"
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
let lib_dir = std::process::Command::new("python3")
|
|
||||||
.arg("-c")
|
|
||||||
.arg("import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
|
|
||||||
.output()
|
|
||||||
.expect("failed to run python3")
|
|
||||||
.stdout;
|
|
||||||
|
|
||||||
let lib_dir = String::from_utf8(lib_dir).unwrap();
|
|
||||||
println!("cargo:rustc-link-search=native={}", lib_dir.trim());
|
|
||||||
|
|
||||||
println!("cargo:rustc-link-lib=python3.13");
|
|
||||||
}
|
|
||||||
+7
-4
@@ -1,8 +1,11 @@
|
|||||||
use flux_rt::{runtime::python::PythonModule, prelude::*};
|
use flux_rt::{
|
||||||
|
runtime::python::{self},
|
||||||
|
FluxModule,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let bro = PythonModule("bro.py".to_string());
|
let gil = python::get_gil();
|
||||||
bro.init();
|
let m = python::import("bro.py", &gil);
|
||||||
|
|
||||||
println!("{:?}", bro.call("hello", vec![]));
|
println!("{:?}", m.call("hello", vec![&"leo"]));
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-103
@@ -1,113 +1,60 @@
|
|||||||
use std::{ffi::{CString, c_char}, fs};
|
use std::fs;
|
||||||
|
|
||||||
use crate::{FluxModule, FluxValue, Serialize};
|
use crate::FluxModule;
|
||||||
|
use cpython::{GILGuard, ObjectProtocol, PyObject, PyTuple, Python, PythonObject, ToPyObject};
|
||||||
|
|
||||||
#[link(name = "python3.13")]
|
pub fn import<'a>(path: &str, gil: &'a GILGuard) -> PythonModule<'a> {
|
||||||
extern "C" {
|
let m = PythonModule {
|
||||||
fn Py_Initialize();
|
path: path.to_string(),
|
||||||
fn Py_Finalize();
|
python: gil.python(),
|
||||||
|
|
||||||
fn PyRun_SimpleString(command: *const i8) -> i32;
|
|
||||||
|
|
||||||
fn PyImport_AddModule(name: *const c_char) -> *mut PyObject;
|
|
||||||
fn PyModule_GetDict(module: *mut PyObject) -> *mut PyObject;
|
|
||||||
fn PyDict_GetItemString(dict: *mut PyObject, key: *const c_char) -> *mut PyObject;
|
|
||||||
|
|
||||||
fn PyObject_CallObject(callable: *mut PyObject, args: *mut PyObject) -> *mut PyObject;
|
|
||||||
fn Py_BuildValue(format: *const c_char, ...) -> *mut PyObject;
|
|
||||||
|
|
||||||
fn PyLong_AsLong(obj: *mut PyObject) -> i64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct PyObject;
|
|
||||||
|
|
||||||
pub struct PythonModule(pub String);
|
|
||||||
|
|
||||||
impl FluxModule for PythonModule {
|
|
||||||
fn init(&self) {
|
|
||||||
let code = fs::read_to_string(&self.0).expect("Failed to read python script");
|
|
||||||
let code = CString::new(code.as_str()).unwrap();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
Py_Initialize();
|
|
||||||
PyRun_SimpleString(code.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&self, func: &str, args: Vec<&dyn Serialize>) -> FluxValue {
|
|
||||||
use std::ffi::CString;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
// 1. Get __main__ module dict
|
|
||||||
let main_str = CString::new("__main__").unwrap();
|
|
||||||
let module = PyImport_AddModule(main_str.as_ptr());
|
|
||||||
let dict = PyModule_GetDict(module);
|
|
||||||
|
|
||||||
// 2. Get function by name
|
|
||||||
let func_name = CString::new(func).unwrap();
|
|
||||||
let func_obj = PyDict_GetItemString(dict, func_name.as_ptr());
|
|
||||||
|
|
||||||
if func_obj.is_null() {
|
|
||||||
panic!("Python function '{}' not found", func);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut fmt = String::from("(");
|
|
||||||
let values: Vec<FluxValue> = args.iter().map(|a| a.serialize()).collect();
|
|
||||||
|
|
||||||
for v in &values {
|
|
||||||
match v {
|
|
||||||
FluxValue::Int(_) => fmt.push('l'), // long
|
|
||||||
FluxValue::Float(_) => fmt.push('d'), // double
|
|
||||||
FluxValue::Str(_) => fmt.push('s'), // string
|
|
||||||
FluxValue::Null => fmt.push('O'), // PyObject*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.push(')');
|
|
||||||
|
|
||||||
let fmt_c = CString::new(fmt).unwrap();
|
|
||||||
|
|
||||||
// Call Py_BuildValue with the right arguments
|
|
||||||
let args_obj: *mut PyObject = match values.as_slice() {
|
|
||||||
[FluxValue::Int(a), FluxValue::Int(b)] => {
|
|
||||||
Py_BuildValue(fmt_c.as_ptr(), *a, *b)
|
|
||||||
}
|
|
||||||
[FluxValue::Float(a), FluxValue::Float(b)] => {
|
|
||||||
Py_BuildValue(fmt_c.as_ptr(), *a, *b)
|
|
||||||
}
|
|
||||||
[FluxValue::Str(a), FluxValue::Str(b)] => {
|
|
||||||
let a_c = CString::new(a.as_str()).unwrap();
|
|
||||||
let b_c = CString::new(b.as_str()).unwrap();
|
|
||||||
Py_BuildValue(fmt_c.as_ptr(), a_c.as_ptr(), b_c.as_ptr())
|
|
||||||
}
|
|
||||||
[FluxValue::Int(a)] => {
|
|
||||||
Py_BuildValue(fmt_c.as_ptr(), *a)
|
|
||||||
}
|
|
||||||
[FluxValue::Float(a)] => {
|
|
||||||
Py_BuildValue(fmt_c.as_ptr(), *a)
|
|
||||||
}
|
|
||||||
[FluxValue::Str(a)] => {
|
|
||||||
let a_c = CString::new(a.as_str()).unwrap();
|
|
||||||
Py_BuildValue(fmt_c.as_ptr(), a_c.as_ptr())
|
|
||||||
}
|
|
||||||
_ => std::ptr::null_mut(),
|
|
||||||
};
|
};
|
||||||
|
m.init();
|
||||||
|
m
|
||||||
|
}
|
||||||
|
|
||||||
let result_obj = PyObject_CallObject(func_obj, args_obj);
|
pub fn get_gil() -> GILGuard {
|
||||||
|
Python::acquire_gil()
|
||||||
|
}
|
||||||
|
|
||||||
if result_obj.is_null() {
|
pub struct PythonModule<'a> {
|
||||||
FluxValue::Null
|
path: String,
|
||||||
|
python: Python<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FluxModule for PythonModule<'_> {
|
||||||
|
fn init(&self) {
|
||||||
|
let code = fs::read_to_string(&self.path).unwrap();
|
||||||
|
self.python.run(&code, None, None).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, func: &str, args: Vec<&dyn crate::Serialize>) -> crate::FluxValue {
|
||||||
|
let module = self.python.import("__main__").unwrap();
|
||||||
|
let func = module.get(self.python, func).unwrap();
|
||||||
|
|
||||||
|
let py_args: Vec<PyObject> = args
|
||||||
|
.iter()
|
||||||
|
.map(|a| match a.serialize() {
|
||||||
|
crate::FluxValue::Int(i) => i.to_py_object(self.python).into_object(),
|
||||||
|
crate::FluxValue::Float(f) => f.to_py_object(self.python).into_object(),
|
||||||
|
crate::FluxValue::Str(s) => s.to_py_object(self.python).into_object(),
|
||||||
|
crate::FluxValue::Null => self.python.None(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let args_tuple = PyTuple::new(self.python, &py_args);
|
||||||
|
|
||||||
|
let result: PyObject = func.call(self.python, args_tuple, None).unwrap();
|
||||||
|
|
||||||
|
if let Ok(i) = result.extract::<i64>(self.python) {
|
||||||
|
crate::FluxValue::Int(i)
|
||||||
|
} else if let Ok(f) = result.extract::<f64>(self.python) {
|
||||||
|
crate::FluxValue::Float(f)
|
||||||
|
} else if let Ok(s) = result.extract::<String>(self.python) {
|
||||||
|
crate::FluxValue::Str(s)
|
||||||
} else {
|
} else {
|
||||||
let value = PyLong_AsLong(result_obj);
|
crate::FluxValue::Null
|
||||||
FluxValue::Int(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn end(&self) {}
|
||||||
fn end(&self) {
|
|
||||||
unsafe {
|
|
||||||
Py_Finalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user