Skip to content

Commit 6918134

Browse files
committed
Pass the hello examples.
1 parent 5ea8cca commit 6918134

File tree

10 files changed

+202
-119
lines changed

10 files changed

+202
-119
lines changed

examples/hello/src/lib.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use std::{fs::OpenOptions, io::Write};
21
use phper::{
2+
arrays::Array,
33
c_str_ptr,
44
classes::{Class, StdClass, This},
55
functions::{create_zend_arg_info, Argument},
@@ -10,11 +10,10 @@ use phper::{
1010
php_info_print_table_end, php_info_print_table_row, php_info_print_table_start,
1111
zend_function_entry, OnUpdateBool, PHP_INI_SYSTEM,
1212
},
13-
values::{ExecuteData, Val},
13+
values::{ExecuteData, SetVal, Val},
1414
Throwable,
1515
};
16-
use phper::arrays::Array;
17-
use phper::values::SetVal;
16+
use std::{fs::OpenOptions, io::Write};
1817

1918
fn module_init(_args: ModuleArgs) -> bool {
2019
true
@@ -70,14 +69,23 @@ pub extern "C" fn get_module(module: &mut Module) {
7069
);
7170

7271
// register classes
73-
let mut std_class = StdClass::new();
74-
std_class.add_property("foo", 100);
75-
std_class.add_method(
76-
"test1",
77-
|_: &mut This, _: &mut [Val]| {
78-
println!("hello test1");
72+
let mut foo_class = StdClass::new();
73+
foo_class.add_property("foo", 100);
74+
foo_class.add_method(
75+
"getFoo",
76+
|this: &mut This, _: &mut [Val]| {
77+
let prop = this.get_property("foo");
78+
Val::from_val(prop)
7979
},
8080
vec![],
8181
);
82-
module.add_class("Test1", std_class);
82+
foo_class.add_method(
83+
"setFoo",
84+
|this: &mut This, arguments: &mut [Val]| {
85+
let prop = this.get_property("foo");
86+
prop.set(&arguments[0]);
87+
},
88+
vec![Argument::by_val("foo")],
89+
);
90+
module.add_class("FooClass", foo_class);
8391
}

phper-sys/php_wrapper.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ void phper_zval_zval(zval *return_value, zval *zv, int copy, int dtor) {
3838
ZVAL_ZVAL(return_value, zv, copy, dtor);
3939
}
4040

41+
void phper_zval_dup(zval *return_value, zval *zv) {
42+
ZVAL_DUP(return_value, zv);
43+
}
44+
45+
void phper_zval_copy(zval *return_value, zval *zv) {
46+
ZVAL_COPY(return_value, zv);
47+
}
48+
4149
zend_string *phper_zval_get_string(zval *op) {
4250
return zval_get_string(op);
4351
}

phper-sys/php_wrapper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ void phper_zval_stringl(zval *return_value, const char *s, size_t len);
1717
char *phper_z_strval_p(const zval *v);
1818
zval *phper_get_this(zend_execute_data *execute_data);
1919
void phper_zval_zval(zval *return_value, zval *zv, int copy, int dtor);
20+
void phper_zval_dup(zval *return_value, zval *zv);
21+
void phper_zval_copy(zval *return_value, zval *zv);
2022
zend_string *phper_zval_get_string(zval *op);
2123
void phper_zend_string_release(zend_string *s);
2224
zend_long phper_zval_get_long(zval *op);

phper/src/arrays.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
use crate::sys::*;
2-
use std::ptr::null_mut;
3-
use std::mem::zeroed;
4-
use crate::values::Val;
5-
use std::ops::{Deref, DerefMut};
1+
use crate::{sys::*, values::Val};
2+
use std::{
3+
mem::zeroed,
4+
ops::{Deref, DerefMut},
5+
ptr::null_mut,
6+
};
67

78
pub struct Array {
89
inner: Box<zend_array>,
@@ -14,15 +15,18 @@ impl Array {
1415
unsafe {
1516
_zend_hash_init(&mut *inner, 0, None, 1);
1617
}
17-
Self {
18-
inner,
19-
}
18+
Self { inner }
2019
}
2120

2221
pub fn insert(&mut self, key: impl AsRef<str>, value: &mut Val) {
2322
let key = key.as_ref();
2423
unsafe {
25-
zend_hash_str_update(&mut *self.inner, key.as_ptr().cast(), key.len(), value.as_mut());
24+
zend_hash_str_update(
25+
&mut *self.inner,
26+
key.as_ptr().cast(),
27+
key.len(),
28+
value.as_mut(),
29+
);
2630
}
2731
}
2832

@@ -35,9 +39,7 @@ impl Array {
3539
}
3640

3741
pub fn len(&mut self) -> usize {
38-
unsafe {
39-
zend_array_count(&mut *self.inner) as usize
40-
}
42+
unsafe { zend_array_count(&mut *self.inner) as usize }
4143
}
4244
}
4345

@@ -59,4 +61,4 @@ impl Drop for Array {
5961
zend_hash_destroy(&mut *self.inner);
6062
}
6163
}
62-
}
64+
}

phper/src/classes.rs

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
functions::{invoke, Argument, Callable, FunctionEntity, FunctionEntry, Method},
33
sys::*,
4-
values::Val,
4+
values::{SetVal, Val},
55
};
66
use once_cell::sync::OnceCell;
77
use std::{
@@ -15,8 +15,8 @@ use std::{
1515
};
1616

1717
pub trait Class: Send + Sync {
18-
fn methods(&self) -> &[FunctionEntity];
19-
fn properties(&self) -> &[PropertyEntity];
18+
fn methods(&mut self) -> &mut [FunctionEntity];
19+
fn properties(&mut self) -> &mut [PropertyEntity];
2020
fn parent(&self) -> Option<&str>;
2121
}
2222

@@ -43,12 +43,16 @@ impl StdClass {
4343
) {
4444
self.method_entities.push(FunctionEntity::new(
4545
name,
46-
Callable::Method(Box::new(handler)),
46+
Callable::Method(Box::new(handler), AtomicPtr::new(null_mut())),
4747
arguments,
4848
));
4949
}
5050

51-
pub fn add_property(&mut self, name: impl ToString, value: i32) {
51+
pub fn add_property(
52+
&mut self,
53+
name: impl ToString,
54+
value: impl SetVal + Send + Sync + 'static,
55+
) {
5256
self.property_entities
5357
.push(PropertyEntity::new(name, value));
5458
}
@@ -60,12 +64,12 @@ impl StdClass {
6064
}
6165

6266
impl Class for StdClass {
63-
fn methods(&self) -> &[FunctionEntity] {
64-
&self.method_entities
67+
fn methods(&mut self) -> &mut [FunctionEntity] {
68+
&mut self.method_entities
6569
}
6670

67-
fn properties(&self) -> &[PropertyEntity] {
68-
&self.property_entities
71+
fn properties(&mut self) -> &mut [PropertyEntity] {
72+
&mut self.property_entities
6973
}
7074

7175
fn parent(&self) -> Option<&str> {
@@ -88,7 +92,6 @@ pub struct ClassEntity {
8892
pub(crate) name: String,
8993
pub(crate) entry: AtomicPtr<ClassEntry>,
9094
pub(crate) class: Box<dyn Class>,
91-
pub(crate) init_once: Once,
9295
pub(crate) function_entries: OnceCell<AtomicPtr<FunctionEntry>>,
9396
}
9497

@@ -98,50 +101,59 @@ impl ClassEntity {
98101
name: name.to_string(),
99102
entry: AtomicPtr::new(null_mut()),
100103
class: Box::new(class),
101-
init_once: Once::new(),
102104
function_entries: Default::default(),
103105
}
104106
}
105107

106-
pub(crate) unsafe fn init(&self) {
107-
self.init_once.call_once(|| {
108-
let mut class_ce = phper_init_class_entry_ex(
109-
self.name.as_ptr().cast(),
110-
self.name.len(),
111-
self.function_entries().load(Ordering::SeqCst).cast(),
112-
);
108+
pub(crate) unsafe fn init(&mut self) {
109+
let mut class_ce = phper_init_class_entry_ex(
110+
self.name.as_ptr().cast(),
111+
self.name.len(),
112+
self.function_entries().load(Ordering::SeqCst).cast(),
113+
);
113114

114-
let parent = self.class.parent().map(|s| match s {
115-
"Exception" | "\\Exception" => zend_ce_exception,
116-
_ => todo!(),
117-
});
118-
119-
let ptr = match parent {
120-
Some(parent) => zend_register_internal_class_ex(&mut class_ce, parent).cast(),
121-
None => zend_register_internal_class(&mut class_ce).cast(),
122-
};
123-
self.entry.store(ptr, Ordering::SeqCst);
115+
let parent = self.class.parent().map(|s| match s {
116+
"Exception" | "\\Exception" => zend_ce_exception,
117+
_ => todo!(),
124118
});
119+
120+
let ptr = match parent {
121+
Some(parent) => zend_register_internal_class_ex(&mut class_ce, parent).cast(),
122+
None => zend_register_internal_class(&mut class_ce).cast(),
123+
};
124+
self.entry.store(ptr, Ordering::SeqCst);
125+
126+
let methods = self.class.methods();
127+
for method in methods {
128+
match &method.handler {
129+
Callable::Method(_, class) => {
130+
class.store(ptr, Ordering::SeqCst);
131+
}
132+
_ => unreachable!(),
133+
}
134+
}
125135
}
126136

127-
pub(crate) unsafe fn declare_properties(&self) {
137+
pub(crate) unsafe fn declare_properties(&mut self) {
128138
let properties = self.class.properties();
129139
for property in properties {
130-
zend_declare_property_long(
140+
let mut val = Val::null();
141+
val.set(&property.value);
142+
zend_declare_property(
131143
self.entry.load(Ordering::SeqCst).cast(),
132144
property.name.as_ptr().cast(),
133145
property.name.len(),
134-
property.value.into(),
146+
val.as_mut(),
135147
Visibility::Public as c_int,
136148
);
137149
}
138150
}
139151

140-
unsafe fn function_entries(&self) -> &AtomicPtr<FunctionEntry> {
152+
unsafe fn function_entries(&mut self) -> &AtomicPtr<FunctionEntry> {
153+
let methods = &*self.class.methods();
154+
141155
self.function_entries.get_or_init(|| {
142-
let mut methods = self
143-
.class
144-
.methods()
156+
let mut methods = methods
145157
.iter()
146158
.map(|method| method.entry())
147159
.collect::<Vec<_>>();
@@ -152,29 +164,44 @@ impl ClassEntity {
152164
}
153165
}
154166

155-
#[repr(transparent)]
156167
pub struct This {
157-
inner: zval,
168+
val: *mut Val,
169+
class: *mut ClassEntry,
158170
}
159171

160172
impl This {
161-
#[inline]
162-
pub unsafe fn from_mut<'a>(ptr: *mut zval) -> &'a mut Self {
163-
assert!(!ptr.is_null(), "ptr should not be null");
164-
&mut *(ptr as *mut Self)
173+
pub(crate) fn new<'a>(val: *mut Val, class: *mut ClassEntry) -> This {
174+
assert!(!val.is_null());
175+
assert!(!class.is_null());
176+
Self { val, class }
177+
}
178+
179+
pub fn get_property(&self, name: impl AsRef<str>) -> &mut Val {
180+
let name = name.as_ref();
181+
unsafe {
182+
let prop = zend_read_property(
183+
self.class as *mut _,
184+
self.val as *mut _,
185+
name.as_ptr().cast(),
186+
name.len(),
187+
0,
188+
null_mut(),
189+
);
190+
Val::from_mut(prop)
191+
}
165192
}
166193
}
167194

168195
pub struct PropertyEntity {
169196
name: String,
170-
value: i32,
197+
value: Box<dyn SetVal + Send + Sync>,
171198
}
172199

173200
impl PropertyEntity {
174-
pub fn new(name: impl ToString, value: i32) -> Self {
201+
pub fn new(name: impl ToString, value: impl SetVal + Send + Sync + 'static) -> Self {
175202
Self {
176203
name: name.to_string(),
177-
value,
204+
value: Box::new(value),
178205
}
179206
}
180207
}

phper/src/functions.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
classes::This,
2+
classes::{ClassEntry, This},
33
errors::Throwable,
44
ini::create_ini_entry_ex,
55
sys::*,
@@ -11,6 +11,7 @@ use std::{
1111
mem::{size_of, transmute, zeroed},
1212
os::raw::{c_char, c_int},
1313
ptr::{null, null_mut},
14+
sync::atomic::{AtomicPtr, Ordering},
1415
};
1516

1617
pub trait Function: Send + Sync {
@@ -45,7 +46,7 @@ where
4546

4647
pub(crate) enum Callable {
4748
Function(Box<dyn Function>),
48-
Method(Box<dyn Method>),
49+
Method(Box<dyn Method>, AtomicPtr<ClassEntry>),
4950
}
5051

5152
#[repr(transparent)]
@@ -173,7 +174,7 @@ pub(crate) unsafe extern "C" fn invoke(
173174
execute_data.num_args()
174175
);
175176
php_error_docref(null(), E_WARNING as i32, s.as_ptr().cast());
176-
().set_val(return_value);
177+
return_value.set(());
177178
return;
178179
}
179180

@@ -183,8 +184,9 @@ pub(crate) unsafe extern "C" fn invoke(
183184
Callable::Function(f) => {
184185
f.call(&mut arguments, return_value);
185186
}
186-
Callable::Method(m) => {
187-
m.call(execute_data.get_this(), &mut arguments, return_value);
187+
Callable::Method(m, class) => {
188+
let mut this = This::new(execute_data.get_this(), class.load(Ordering::SeqCst));
189+
m.call(&mut this, &mut arguments, return_value);
188190
}
189191
}
190192
}

phper/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ Now the library don't support `ZTS`, the template is using `thread_local!` inste
2626
Version `0.1.x` will be a preview version.
2727
*/
2828

29-
mod errors;
30-
mod utils;
3129
pub mod arrays;
3230
pub mod classes;
3331
pub mod cmd;
32+
mod errors;
3433
pub mod functions;
3534
pub mod ini;
3635
pub mod logs;
3736
pub mod modules;
3837
pub mod strings;
38+
mod utils;
3939
pub mod values;
4040

4141
pub use crate::errors::*;

0 commit comments

Comments
 (0)