#[allow(unused)]
#[cfg(test)]
mod tests {
use std::{
ffi::{CStr, CString, c_char, c_void},
ptr,
};
use pixelscript::{
python::PythonScripting,
shared::{
PixelScript, PtrMagic, func::pxs_Func, pxs_Runtime, var::{pxs_Var, pxs_VarT}
},
*,
};
macro_rules! create_raw_string {
($rstr:expr) => {{ CString::new($rstr).unwrap().into_raw() }};
}
macro_rules! free_raw_string {
($rptr:expr) => {{
if !$rptr.is_null() {
unsafe {
let _ = std::ffi::CString::from_raw($rptr);
}
}
}};
}
struct Diary {
owner: String,
items: Vec<String>,
}
impl Diary {
pub fn new(owner: String) -> Self {
Diary {
owner,
items: vec![],
}
}
}
impl PtrMagic for Diary {}
pub extern "C" fn free_diary(ptr: *mut c_void) {
println!("DIARY FREED");
let _ = unsafe { Diary::from_raw(ptr as *mut Diary) };
}
extern "C" fn add_item(args: pxs_VarT) -> pxs_VarT {
unsafe {
let pixel_object_var = pxs_listget(args, 1);
let host_ptr = pxs_gethost(pxs_listget(args, 0), pixel_object_var);
let d = Diary::from_borrow(host_ptr as *mut Diary);
let item = pxs_listget(args, 2);
let contents = pxs_getstring(item);
let str = own_string!(contents);
d.items.push(str);
pxs_newnull()
}
}
extern "C" fn new_diary(args: pxs_VarT) -> pxs_VarT {
println!("Calling new diar right?");
unsafe {
let p_name = pxs_Var::from_borrow(pxs_listget(args, 1));
let p_name = p_name.get_string().unwrap();
let p = Diary::new(p_name.clone());
let typename = create_raw_string!("Diary");
let ptr = Diary::into_raw(p) as *mut c_void;
let pixel_object = pxs_newobject(ptr, free_diary, typename);
let add_item_raw = create_raw_string!("add_item");
pxs_object_add_reffunc(pixel_object, add_item_raw, add_item);
let var = pxs_newhost(pixel_object);
free_raw_string!(add_item_raw);
free_raw_string!(typename);
let dbg = own_string!(pxs_debugvar(var));
println!("{dbg}");
var
}
}
struct Person {
name: String,
}
impl Person {
pub fn new(n_name: String) -> Self {
Person { name: n_name }
}
pub fn set_name(&mut self, n_name: String) {
self.name = n_name;
}
pub fn get_name(&self) -> String {
self.name.clone()
}
}
impl PtrMagic for Person {}
pub extern "C" fn free_person(ptr: *mut c_void) {
println!("PERSON FREED");
let _ = unsafe { Person::from_raw(ptr as *mut Person) };
}
pub extern "C" fn set_name(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let pixel_object_var = pxs_listget(args, 1);
let host_ptr = pxs_gethost(pxs_listget(args, 0), pixel_object_var);
let p = Person::from_borrow(host_ptr as *mut Person);
let name = {
let first_arg = pxs_Var::from_borrow(pxs_listget(args, 2));
if first_arg.is_string() {
first_arg
} else {
pxs_Var::from_borrow(pxs_listget(args, 3))
}
};
p.set_name(name.get_string().unwrap().clone());
pxs_Var::into_raw(pxs_Var::new_null())
}
}
pub extern "C" fn get_name(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let pixel_object_var = pxs_listget(args, 1);
let host_ptr = pxs_gethost(pxs_listget(args, 0), pixel_object_var);
let p = Person::from_borrow(host_ptr as *mut Person);
pxs_Var::new_string(p.get_name().clone()).into_raw()
}
}
pub extern "C" fn new_person(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let p_name = pxs_Var::from_borrow(pxs_listget(args, 1));
let p_name = p_name.get_string().unwrap();
let p = Person::new(p_name.clone());
let typename = create_raw_string!("Person");
let ptr = Person::into_raw(p) as *mut c_void;
let pixel_object = pxs_newobject(ptr, free_person, typename);
let set_name_raw = create_raw_string!("set_name");
let get_name_raw = create_raw_string!("get_name");
pxs_object_add_reffunc(pixel_object, set_name_raw, set_name);
pxs_object_add_reffunc(pixel_object, get_name_raw, get_name);
let var = pxs_newhost(pixel_object);
free_raw_string!(set_name_raw);
free_raw_string!(get_name_raw);
free_raw_string!(typename);
var
}
}
pub extern "C" fn print_wrapper(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let runtime = pxs_listget(args, 0);
let mut string = String::new();
for i in 1..pxs_listlen(args) {
let var = pxs_tostring(runtime, pxs_listget(args, i));
if let Ok(s) = (*var).get_string() {
string.push_str(format!("{s} ").as_str());
}
pxs_freevar(var);
}
println!("From Runtime: {string}");
}
pxs_Var::new_null().into_raw()
}
pub extern "C" fn add_wrapper(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let n1 = pxs_Var::from_borrow(pxs_listget(args, 1));
let n2 = pxs_Var::from_borrow(pxs_listget(args, 2));
pxs_Var::new_i64(n1.value.i64_val + n2.value.i64_val).into_raw()
}
}
pub extern "C" fn sub_wrapper(args: *mut pxs_Var) -> *mut pxs_Var {
unsafe {
let n1 = pxs_Var::from_borrow(pxs_listget(args, 1));
let n2 = pxs_Var::from_borrow(pxs_listget(args, 2));
pxs_Var::new_i64(n1.value.i64_val - n2.value.i64_val).into_raw()
}
}
unsafe extern "C" fn file_loader(file_path: *const c_char) -> *mut c_char {
if file_path.is_null() {
return std::ptr::null_mut();
}
let file_path = unsafe { CStr::from_ptr(file_path).to_str().unwrap() };
if file_path.is_empty() {
return create_raw_string!("");
}
let file_exists = std::fs::exists(file_path).unwrap();
if !file_exists {
return create_raw_string!("");
}
let contents = std::fs::read_to_string(file_path).unwrap();
create_raw_string!(contents)
}
unsafe extern "C" fn dir_reader(dir_path: *const c_char) -> pxs_VarT {
let dir_path = unsafe { CStr::from_ptr(dir_path).to_str().unwrap() };
if dir_path.is_empty() {
return pxs_newnull();
}
let dir_exists = std::fs::exists(dir_path).unwrap();
if !dir_exists {
return pxs_newnull();
}
let files = std::fs::read_dir(dir_path).unwrap();
let result = pxs_newlist();
for f in files {
let entry = f.unwrap();
let raw = create_raw_string!(entry.file_name().into_string().unwrap());
pxs_listadd(result, pxs_newstring(raw));
unsafe{free_raw_string!(raw);}
}
result
}
unsafe extern "C" fn call_function(args: pxs_VarT) -> pxs_VarT {
let func = pxs_listget(args, 1);
let argc = pxs_listlen(args);
let res = if argc > 2 {
pxs_varcall(
pxs_listget(args, 0),
func,
pxs_newcopy(pxs_listget(args, 2)),
)
} else {
pxs_varcall(pxs_listget(args, 0), func, pxs_newlist())
};
res
}
fn test_add_module() {
println!("Inside Test add module");
pxs_initialize();
let module_name = create_raw_string!("pxs");
let module = pxs_newmod(module_name);
let add_name = create_raw_string!("add");
let n1_name = create_raw_string!("n1");
let n2_name: *mut i8 = create_raw_string!("n2");
pxs_addfunc(module, add_name, add_wrapper);
let n1 = pxs_newint(1);
let n2 = pxs_newint(2);
pxs_addvar(module, n1_name, n1);
pxs_addvar(module, n2_name, n2);
let name = create_raw_string!("print");
pxs_addfunc(module, name, print_wrapper);
let var_name = create_raw_string!("name");
let jordan = create_raw_string!("Jordan C");
let var = pxs_newstring(jordan);
pxs_addvar(module, var_name, var);
let object_name = create_raw_string!("Person");
pxs_addobject(module, object_name, new_person);
let call_name = create_raw_string!("call_function");
pxs_addfunc(module, call_name, call_function);
free_raw_string!(call_name);
let math_module_name = create_raw_string!("math");
let math_module = pxs_newmod(math_module_name);
let sub_name = create_raw_string!("sub");
let zero_name = create_raw_string!("ZERO");
let diary_name = create_raw_string!("Diary");
let ddiary_name = create_raw_string!("DDiary");
pxs_addobject(math_module, diary_name, new_diary);
pxs_addfunc(math_module, sub_name, sub_wrapper);
pxs_addvar(math_module, zero_name, pxs_newint(0));
let args = pxs_newlist();
pxs_listadd(args, pxs_Var::new_string("Test".to_string()).into_raw());
pxs_addvar(math_module, ddiary_name, pxs_newfactory(new_diary, args));
pxs_add_submod(module, math_module);
pxs_addmod(module);
free_raw_string!(ddiary_name);
free_raw_string!(diary_name);
free_raw_string!(zero_name);
free_raw_string!(module_name);
free_raw_string!(add_name);
free_raw_string!(n1_name);
free_raw_string!(n2_name);
free_raw_string!(object_name);
free_raw_string!(name);
free_raw_string!(var_name);
free_raw_string!(math_module_name);
free_raw_string!(sub_name);
}
#[test]
fn test_execute() {
println!("Test starting");
pxs_initialize();
test_add_module();
pxs_set_filereader(file_loader);
pxs_set_dirreader(dir_reader);
let py_code = r#"
import pxs
from pad.ft_object import function_from_outside
from pxs.math import *
diary = Diary("Jordan")
diary2 = Diary("Jordan2")
print(f'diary is: {diary} and diary2 is: {diary2}')
diary.add_item("Yo test dog")
print(diary)
print(f"DDiary: {DDiary}")
pxs.print(__name__)
function_from_outside() # Should print something
msg = "Welcome " + pxs.name
pxs.print(msg)
result = pxs.add(pxs.n1, pxs.n2)
pxs.print(f"Module result: {result}")
if result != 3:
raise "Math, Expected 3, got " + str(result)
res = pxs.math.sub(2, 1)
pxs.print(res)
if res != 1:
raise Exception("Math, Expected 1, got " + str(res))
zero = pxs.math.ZERO
if zero != 0:
raise Exception("Math, Expected 0, got " + str(zero))
person = pxs.Person("Jordan")
person2 = pxs.Person("Evelyn")
pxs.print(person2.get_name())
pxs.print(person)
print(person.get_name())
person.set_name("Jordan Castro")
print(person.get_name())
print(type(person).__name__)
print(type(pxs.Person).__name__)
def hadd(n1, n2):
return n1 + n2
print(pxs.call_function(hadd, [1,2]))
def get_pi():
return 3.1459
print(pxs.call_function(get_pi))
"#;
let code = create_raw_string!(py_code);
let file_name = create_raw_string!("<test>");
let err = own_var!(pxs_exec(pxs_Runtime::pxs_Python, code, file_name));
unsafe {
free_raw_string!(code);
free_raw_string!(file_name);
}
pxs_startthread();
pxs_startthread();
pxs_stopthread();
pxs_stopthread();
pxs_finalize();
assert!(err.is_null(), "Python Error is not empty: {}", err.get_string().unwrap());
}
}