Working python arg and return

This commit is contained in:
2025-08-25 02:28:25 +02:00
parent 1c5e90068c
commit e940987abb
6 changed files with 154 additions and 121 deletions
Generated
+96
View File
@@ -2,6 +2,102 @@
# It is not intended for manual editing.
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]]
name = "flux-rt"
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
View File
@@ -2,6 +2,6 @@
name = "flux-rt"
version = "0.1.0"
edition = "2021"
build = "build.rs"
[dependencies]
cpython = "0.7.2"
+1 -1
View File
@@ -1,3 +1,3 @@
def hello(name: str) -> str:
def hello(name):
print("Hello, bro! " + name)
return "Idk, return value i guess"
-13
View File
@@ -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
View File
@@ -1,8 +1,11 @@
use flux_rt::{runtime::python::PythonModule, prelude::*};
use flux_rt::{
runtime::python::{self},
FluxModule,
};
fn main() {
let bro = PythonModule("bro.py".to_string());
bro.init();
let gil = python::get_gil();
let m = python::import("bro.py", &gil);
println!("{:?}", bro.call("hello", vec![]));
println!("{:?}", m.call("hello", vec![&"leo"]));
}
+50 -103
View File
@@ -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")]
extern "C" {
fn Py_Initialize();
fn Py_Finalize();
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(),
pub fn import<'a>(path: &str, gil: &'a GILGuard) -> PythonModule<'a> {
let m = PythonModule {
path: path.to_string(),
python: gil.python(),
};
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() {
FluxValue::Null
pub struct PythonModule<'a> {
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 {
let value = PyLong_AsLong(result_obj);
FluxValue::Int(value)
}
crate::FluxValue::Null
}
}
fn end(&self) {
unsafe {
Py_Finalize();
}
}
fn end(&self) {}
}