Skip to content

Adjust module api. #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Re-adjust.
  • Loading branch information
jmjoy committed Dec 29, 2022
commit d3b74dce2c75cd24432c91cdb69639cd531a60cc
10 changes: 5 additions & 5 deletions examples/complex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use phper::{
classes::{ClassEntity, Visibility},
functions::Argument,
ini::{ini_get, Policy},
modules::{Module, ModuleEntry},
modules::Module,
objects::StateObj,
php_get_module,
values::ZVal,
Expand Down Expand Up @@ -50,10 +50,10 @@ pub fn get_module() -> Module {
);

// register hook functions
module.on_module_init(|_: &ModuleEntry| true);
module.on_module_shutdown(|_| true);
module.on_request_init(|_| true);
module.on_request_shutdown(|_| true);
module.on_module_init(|| true);
module.on_module_shutdown(|| true);
module.on_request_init(|| true);
module.on_request_shutdown(|| true);

// register functions
module
Expand Down
4 changes: 2 additions & 2 deletions examples/http-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ pub fn get_module() -> Module {
let rt = Arc::new(rt);
let rt_ = rt.clone();

module.on_module_init(move |_| {
module.on_module_init(move || {
let guard = rt_.enter();
forget(guard);
true
});
module.on_module_shutdown(move |_| {
module.on_module_shutdown(move || {
drop(rt);
true
});
Expand Down
2 changes: 1 addition & 1 deletion phper-doc/doc/_06_module/_01_hooks/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub fn get_module() -> Module {
env!("CARGO_PKG_AUTHORS"),
);

module.on_module_init(|_| {
module.on_module_init(|| {
// Do somethings in `MINIT` stage.
true
});
Expand Down
180 changes: 31 additions & 149 deletions phper/src/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
//! Apis relate to [crate::sys::zend_module_entry].

use crate::{
arrays::ZArr,
c_str_ptr,
classes::ClassEntity,
constants::Constant,
Expand All @@ -25,20 +24,19 @@ use crate::{
};
use std::{
collections::HashMap,
ffi::{CString, CStr},
marker::PhantomData,
mem::{size_of, take, transmute, zeroed, ManuallyDrop},
ffi::CString,
mem::{size_of, take, transmute, zeroed},
os::raw::{c_int, c_uchar, c_uint, c_ushort},
ptr::{null, null_mut},
rc::Rc, sync::Mutex,
rc::Rc,
};
use once_cell::sync::Lazy;

/// Global pointer hold the Module builder.
/// Because PHP is single threaded, so there is no lock here.
static mut GLOBAL_MODULE: *mut Module = null_mut();

unsafe extern "C" fn module_startup(_type: c_int, module_number: c_int) -> c_int {
let module_entry = ModuleEntry::from_globals_mut(module_number);
let module_name = module_entry.name().to_bytes().to_vec();
let module = module_entry.get_module_mut();
debug_assert_eq!(module_name, module.name.to_bytes());
let module = GLOBAL_MODULE.as_mut().unwrap();

ini::register(&module.ini_entities, module_number);

Expand All @@ -52,49 +50,42 @@ unsafe extern "C" fn module_startup(_type: c_int, module_number: c_int) -> c_int
}

match take(&mut module.module_init) {
Some(f) => f(module_entry) as c_int,
Some(f) => f() as c_int,
None => 1,
}
}

unsafe extern "C" fn module_shutdown(_type: c_int, module_number: c_int) -> c_int {
dbg!("module_shutdown");
let module_entry = ModuleEntry::from_globals_mut(module_number);
let module_name = module_entry.name().to_bytes().to_vec();
let module = module_entry.get_module_mut();
debug_assert_eq!(module_name, module.name.to_bytes());
let module = GLOBAL_MODULE.as_mut().unwrap();

ini::unregister(module_number);

match take(&mut module.module_shutdown) {
Some(f) => f(module_entry) as c_int,
Some(f) => f() as c_int,
None => 1,
}
}

unsafe extern "C" fn request_startup(_type: c_int, module_number: c_int) -> c_int {
let module_entry = ModuleEntry::from_globals(module_number);
let module = module_entry.get_module();
unsafe extern "C" fn request_startup(_type: c_int, _module_number: c_int) -> c_int {
let module = GLOBAL_MODULE.as_ref().unwrap();

match &module.request_init {
Some(f) => f(module_entry) as c_int,
Some(f) => f() as c_int,
None => 1,
}
}

unsafe extern "C" fn request_shutdown(_type: c_int, module_number: c_int) -> c_int {
let module_entry = ModuleEntry::from_globals(module_number);
let module = module_entry.get_module();
unsafe extern "C" fn request_shutdown(_type: c_int, _module_number: c_int) -> c_int {
let module = GLOBAL_MODULE.as_ref().unwrap();

match &module.request_shutdown {
Some(f) => f(module_entry) as c_int,
Some(f) => f() as c_int,
None => 1,
}
}

unsafe extern "C" fn module_info(zend_module: *mut zend_module_entry) {
let module_entry = ModuleEntry::from_ptr(zend_module);
let module = module_entry.get_module();
let module = GLOBAL_MODULE.as_ref().unwrap();

php_info_print_table_start();
if !module.version.as_bytes().is_empty() {
Expand All @@ -117,10 +108,10 @@ pub struct Module {
name: CString,
version: CString,
author: CString,
module_init: Option<Box<dyn FnOnce(&ModuleEntry) -> bool + Send + Sync>>,
module_shutdown: Option<Box<dyn FnOnce(&ModuleEntry) -> bool + Send + Sync>>,
request_init: Option<Box<dyn Fn(&ModuleEntry) -> bool + Send + Sync>>,
request_shutdown: Option<Box<dyn Fn(&ModuleEntry) -> bool + Send + Sync>>,
module_init: Option<Box<dyn FnOnce() -> bool + Send + Sync>>,
module_shutdown: Option<Box<dyn FnOnce() -> bool + Send + Sync>>,
request_init: Option<Box<dyn Fn() -> bool + Send + Sync>>,
request_shutdown: Option<Box<dyn Fn() -> bool + Send + Sync>>,
function_entities: Vec<FunctionEntity>,
class_entities: Vec<ClassEntity<()>>,
constants: Vec<Constant>,
Expand Down Expand Up @@ -150,28 +141,22 @@ impl Module {
}

/// Register `MINIT` hook.
pub fn on_module_init(
&mut self, func: impl FnOnce(&ModuleEntry) -> bool + Send + Sync + 'static,
) {
pub fn on_module_init(&mut self, func: impl FnOnce() -> bool + Send + Sync + 'static) {
self.module_init = Some(Box::new(func));
}

/// Register `MSHUTDOWN` hook.
pub fn on_module_shutdown(
&mut self, func: impl FnOnce(&ModuleEntry) -> bool + Send + Sync + 'static,
) {
pub fn on_module_shutdown(&mut self, func: impl FnOnce() -> bool + Send + Sync + 'static) {
self.module_shutdown = Some(Box::new(func));
}

/// Register `RINIT` hook.
pub fn on_request_init(&mut self, func: impl Fn(&ModuleEntry) -> bool + Send + Sync + 'static) {
pub fn on_request_init(&mut self, func: impl Fn() -> bool + Send + Sync + 'static) {
self.request_init = Some(Box::new(func));
}

/// Register `RSHUTDOWN` hook.
pub fn on_request_shutdown(
&mut self, func: impl Fn(&ModuleEntry) -> bool + Send + Sync + 'static,
) {
pub fn on_request_shutdown(&mut self, func: impl Fn() -> bool + Send + Sync + 'static) {
self.request_shutdown = Some(Box::new(func));
}

Expand Down Expand Up @@ -230,21 +215,21 @@ impl Module {

let module = Box::new(self);

let mut entry: Box<zend_module_entry> = Box::new(zend_module_entry {
let entry: Box<zend_module_entry> = Box::new(zend_module_entry {
size: size_of::<zend_module_entry>() as c_ushort,
zend_api: ZEND_MODULE_API_NO as c_uint,
zend_debug: ZEND_DEBUG as c_uchar,
zts: USING_ZTS as c_uchar,
ini_entry: null(),
deps: null(),
name: null(),
name: module.name.as_ptr(),
functions: module.function_entries(),
module_startup_func: Some(module_startup),
module_shutdown_func: Some(module_shutdown),
request_startup_func: Some(request_startup),
request_shutdown_func: Some(request_shutdown),
info_func: Some(module_info),
version: null(),
version: module.version.as_ptr(),
globals_size: 0,
#[cfg(phper_zts)]
globals_id_ptr: std::ptr::null_mut(),
Expand All @@ -260,12 +245,8 @@ impl Module {
build_id: phper_get_zend_module_build_id(),
});

// Hide module pointer after name.
let mut name: Vec<u8> =
Vec::with_capacity(module.name.as_bytes_with_nul().len() + size_of::<usize>());
name.extend_from_slice(module.name.as_bytes_with_nul());
name.extend_from_slice(&(Box::into_raw(module) as usize).to_le_bytes());
entry.name = ManuallyDrop::new(name).as_ptr().cast();
assert!(GLOBAL_MODULE.is_null(), "GLOBAL_MODULE has registered");
GLOBAL_MODULE = Box::into_raw(module);

Box::into_raw(entry)
}
Expand All @@ -284,102 +265,3 @@ impl Module {
Box::into_raw(entries.into_boxed_slice()).cast()
}
}

/// Wrapper of [`zend_module_entry`](crate::sys::zend_module_entry).
#[repr(transparent)]
pub struct ModuleEntry {
inner: zend_module_entry,
_p: PhantomData<*mut ()>,
}

impl ModuleEntry {
/// Wraps a raw pointer.
///
/// # Safety
///
/// Create from raw pointer.
///
/// # Panics
///
/// Panics if pointer is null.
#[inline]
pub unsafe fn from_ptr<'a>(ptr: *const zend_module_entry) -> &'a Self {
(ptr as *const Self).as_ref().expect("ptr should't be null")
}

/// Wraps a raw pointer.
///
/// # Safety
///
/// Create from raw pointer.
///
/// # Panics
///
/// Panics if pointer is null.
#[inline]
unsafe fn from_mut_ptr<'a>(ptr: *mut zend_module_entry) -> &'a mut Self {
(ptr as *mut Self).as_mut().expect("ptr should't be null")
}

/// Wraps a raw pointer, return None if pointer is null.
///
/// # Safety
///
/// Create from raw pointer.
#[inline]
pub unsafe fn try_from_ptr<'a>(ptr: *const zend_module_entry) -> Option<&'a Self> {
(ptr as *const Self).as_ref()
}

/// Returns a raw pointer wrapped.
pub const fn as_ptr(&self) -> *const zend_module_entry {
&self.inner
}

/// Get the name of module.
pub fn name(&self) -> &CStr {
unsafe {
CStr::from_ptr(self.inner.name)
}
}

#[inline]
fn from_globals(module_number: c_int) -> &'static Self {
Self::from_globals_mut(module_number)
}

fn from_globals_mut(module_number: c_int) -> &'static mut Self {
unsafe {
for (_, ptr) in ZArr::from_mut_ptr(&mut module_registry).iter_mut() {
let module = phper_z_ptr_p(ptr.as_ptr()) as *mut zend_module_entry;
dbg!(CStr::from_ptr((*module).name).to_str());
if (*module).module_number == module_number {
return Self::from_mut_ptr(module);
}
}
panic!("Find module_entry from module_number failed");
}
}

#[inline]
unsafe fn get_module(&self) -> &Module {
Self::inner_get_module((*self.as_ptr()).name as *mut u8)
}

#[inline]
unsafe fn get_module_mut(&mut self) -> &mut Module {
Self::inner_get_module((*self.as_ptr()).name as *mut u8)
}

unsafe fn inner_get_module<'a>(mut ptr: *mut u8) -> &'a mut Module {
while *ptr != 0 {
ptr = ptr.offset(1);
}
let mut buf = [0u8; size_of::<usize>()];
for (i, b) in buf.iter_mut().enumerate() {
*b = *ptr.add(i + 1);
}
let module = usize::from_le_bytes(buf) as *mut Module;
module.as_mut().unwrap()
}
}
1 change: 1 addition & 0 deletions tests/integration/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fn test_cli() {
&tests_php_dir.join("ini.php"),
&tests_php_dir.join("references.php"),
&tests_php_dir.join("errors.php"),
&tests_php_dir.join("reflection.php"),
],
);
}
Expand Down
18 changes: 18 additions & 0 deletions tests/integration/tests/php/reflection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

// Copyright (c) 2022 PHPER Framework Team
// PHPER is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2. You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.


require_once __DIR__ . '/_common.php';

$ext = new ReflectionExtension("integration");
assert_eq($ext->getName(), "integration");
assert_eq($ext->getVersion(), "0.0.0");