mirror of
https://github.com/icewind1991/ivory.git
synced 2026-06-03 18:54:07 +02:00
cleanup
This commit is contained in:
parent
99bdad5ec0
commit
aa1e5d7dca
14 changed files with 86 additions and 85 deletions
|
|
@ -15,7 +15,7 @@ fn hello_other(other: String) {
|
||||||
|
|
||||||
#[ivory_export]
|
#[ivory_export]
|
||||||
fn hello_world() {
|
fn hello_world() {
|
||||||
printf("Hello world, Rust2!");
|
printf("Hello world, Rust!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ivory_module!({
|
ivory_module!({
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.50"
|
|
||||||
ivory = { path = "../../ivory", version = "0.1.0" }
|
ivory = { path = "../../ivory", version = "0.1.0" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@
|
||||||
- build with `cargo build`
|
- build with `cargo build`
|
||||||
- run php with the module and call the defined method
|
- run php with the module and call the defined method
|
||||||
```bash
|
```bash
|
||||||
php -d extension=target/debug/libhelloworld.so -r 'helloworld();'`
|
php -d extension=../../target/debug/libhelloworld.so -r 'helloworld();'`
|
||||||
```
|
```
|
||||||
|
|
@ -8,7 +8,7 @@ fn hello_other(other: String) {
|
||||||
|
|
||||||
#[ivory_export]
|
#[ivory_export]
|
||||||
fn hello_world() {
|
fn hello_world() {
|
||||||
printf("Hello world, Rust2!");
|
printf("Hello world, Rust!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ivory_module!({
|
ivory_module!({
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ repository = "https://github.com/rethinkphp/php-rs"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.50"
|
|
||||||
ivory-macro = { version = "0.1", path = "macro" }
|
ivory-macro = { version = "0.1", path = "macro" }
|
||||||
ivory-sys = { version = "7.3", path = "sys" }
|
ivory-sys = { version = "7.3", path = "sys" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,26 @@ extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream, TokenTree};
|
use proc_macro2::{Span, TokenStream, TokenTree};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{AttributeArgs, Expr, FieldValue, FnArg, Ident, Item, ItemFn, LitStr, parse2, parse_macro_input, Pat, Type};
|
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
use syn::{
|
||||||
|
parse2, parse_macro_input, AttributeArgs, Expr, FieldValue, FnArg, Ident, Item, ItemFn, LitStr,
|
||||||
|
Pat, Type,
|
||||||
|
};
|
||||||
|
|
||||||
/// See the [crate documentation](index.html) for details
|
/// See the [crate documentation](index.html) for details
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn ivory_export(attr: proc_macro::TokenStream, input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn ivory_export(
|
||||||
|
attr: proc_macro::TokenStream,
|
||||||
|
input: proc_macro::TokenStream,
|
||||||
|
) -> proc_macro::TokenStream {
|
||||||
let input: TokenStream = input.into();
|
let input: TokenStream = input.into();
|
||||||
let item = syn::parse2::<Item>(input).unwrap();
|
let item = syn::parse2::<Item>(input).unwrap();
|
||||||
let _attr = parse_macro_input!(attr as AttributeArgs);
|
let _attr = parse_macro_input!(attr as AttributeArgs);
|
||||||
|
|
||||||
let output = match item {
|
let output = match item {
|
||||||
Item::Fn(item_fn) => {
|
Item::Fn(item_fn) => export_fn(item_fn).into(),
|
||||||
export_fn(item_fn).into()
|
_ => unimplemented!(),
|
||||||
}
|
|
||||||
_ => unimplemented!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// panic!("{}", output);
|
// panic!("{}", output);
|
||||||
|
|
@ -38,9 +42,7 @@ fn export_fn(item: ItemFn) -> TokenStream {
|
||||||
unimplemented!("generics are not supported for exported functions");
|
unimplemented!("generics are not supported for exported functions");
|
||||||
}
|
}
|
||||||
|
|
||||||
let args: Vec<(String, Type, bool, Span)> = decl.inputs.into_iter()
|
let args: Vec<(String, Type, bool, Span)> = decl.inputs.into_iter().map(get_arg_info).collect();
|
||||||
.map(get_arg_info)
|
|
||||||
.collect();
|
|
||||||
let arg_count = args.len() as u32;
|
let arg_count = args.len() as u32;
|
||||||
|
|
||||||
let arg_defs = args.iter().map(|(name, _type, is_ref, _)| {
|
let arg_defs = args.iter().map(|(name, _type, is_ref, _)| {
|
||||||
|
|
@ -77,7 +79,7 @@ fn export_fn(item: ItemFn) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
const #meta_name: ::ivory::zend::FunctionMeta = ::ivory::zend::FunctionMeta{
|
const #meta_name: ::ivory::zend::FunctionMeta = ::ivory::zend::FunctionMeta{
|
||||||
name: {concat!(#name_str, "\0").as_ptr() as *const ::libc::c_char},
|
name: {concat!(#name_str, "\0").as_ptr() as *const ::std::os::raw::c_char},
|
||||||
func: #name,
|
func: #name,
|
||||||
args: &[ #(#arg_defs),*]
|
args: &[ #(#arg_defs),*]
|
||||||
};
|
};
|
||||||
|
|
@ -89,14 +91,17 @@ fn get_arg_info(arg: FnArg) -> (String, Type, bool, Span) {
|
||||||
FnArg::Captured(cap) => {
|
FnArg::Captured(cap) => {
|
||||||
let arg_type = cap.ty;
|
let arg_type = cap.ty;
|
||||||
match cap.pat {
|
match cap.pat {
|
||||||
Pat::Ident(ident_pat) => {
|
Pat::Ident(ident_pat) => (
|
||||||
(ident_pat.ident.to_string(), arg_type, ident_pat.by_ref.is_some(), ident_pat.span())
|
ident_pat.ident.to_string(),
|
||||||
},
|
arg_type,
|
||||||
|
ident_pat.by_ref.is_some(),
|
||||||
|
ident_pat.span(),
|
||||||
|
),
|
||||||
Pat::Ref(_ref_pat) => unimplemented!(),
|
Pat::Ref(_ref_pat) => unimplemented!(),
|
||||||
_ => panic!()
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => panic!("only normal function arguments are supported")
|
_ => panic!("only normal function arguments are supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,10 +114,8 @@ pub fn ivory_module(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let mut tokens = input.into_iter();
|
let mut tokens = input.into_iter();
|
||||||
let token = tokens.next().unwrap();
|
let token = tokens.next().unwrap();
|
||||||
let group = match token {
|
let group = match token {
|
||||||
TokenTree::Group(group) => {
|
TokenTree::Group(group) => group,
|
||||||
group
|
_ => panic!("macro input must be a group"),
|
||||||
}
|
|
||||||
_ => panic!("macro input must be a group")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields = group.stream();
|
let fields = group.stream();
|
||||||
|
|
@ -161,8 +164,9 @@ pub fn ivory_module(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_c_str(input: TokenStream) -> TokenStream {
|
fn into_c_str(input: TokenStream) -> TokenStream {
|
||||||
let tokens: Vec<TokenTree> = input.into_iter().map(|token| {
|
let tokens: Vec<TokenTree> = input
|
||||||
match token.clone() {
|
.into_iter()
|
||||||
|
.map(|token| match token.clone() {
|
||||||
TokenTree::Literal(_lit) => {
|
TokenTree::Literal(_lit) => {
|
||||||
let mut tokens = TokenStream::new();
|
let mut tokens = TokenStream::new();
|
||||||
tokens.extend(vec![token.clone()]);
|
tokens.extend(vec![token.clone()]);
|
||||||
|
|
@ -170,7 +174,7 @@ fn into_c_str(input: TokenStream) -> TokenStream {
|
||||||
Ok(lit_str) => {
|
Ok(lit_str) => {
|
||||||
let val = lit_str.value();
|
let val = lit_str.value();
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
{ concat!(#val, "\0").as_ptr() as *const ::libc::c_char }
|
{ concat!(#val, "\0").as_ptr() as *const ::std::os::raw::c_char }
|
||||||
};
|
};
|
||||||
if let Some(tree) = tokens.into_iter().next() {
|
if let Some(tree) = tokens.into_iter().next() {
|
||||||
tree
|
tree
|
||||||
|
|
@ -178,12 +182,12 @@ fn into_c_str(input: TokenStream) -> TokenStream {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => token
|
Err(_) => token,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => token
|
_ => token,
|
||||||
}
|
})
|
||||||
}).collect();
|
.collect();
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
output.extend(tokens.into_iter());
|
output.extend(tokens.into_iter());
|
||||||
output
|
output
|
||||||
|
|
@ -193,31 +197,29 @@ fn get_function_names(struct_def: TokenStream) -> Vec<String> {
|
||||||
let expr: Expr = parse2(struct_def).unwrap();
|
let expr: Expr = parse2(struct_def).unwrap();
|
||||||
let expr = get_field_expr(expr, "functions").unwrap();
|
let expr = get_field_expr(expr, "functions").unwrap();
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Reference(ref_expr) => {
|
Expr::Reference(ref_expr) => match *ref_expr.expr {
|
||||||
match *ref_expr.expr {
|
Expr::Array(arr) => arr
|
||||||
Expr::Array(arr) => {
|
.elems
|
||||||
arr.elems.into_iter().map(|element: Expr| {
|
.into_iter()
|
||||||
let tokens: TokenStream = quote!(#element);
|
.map(|element: Expr| {
|
||||||
let tree = tokens.into_iter().next().unwrap();
|
let tokens: TokenStream = quote!(#element);
|
||||||
match tree {
|
let tree = tokens.into_iter().next().unwrap();
|
||||||
TokenTree::Ident(ident) => {
|
match tree {
|
||||||
ident.to_string()
|
TokenTree::Ident(ident) => ident.to_string(),
|
||||||
}
|
_ => panic!(),
|
||||||
_ => panic!()
|
}
|
||||||
}
|
})
|
||||||
}).collect()
|
.collect(),
|
||||||
}
|
_ => panic!(),
|
||||||
_ => panic!()
|
},
|
||||||
}
|
_ => panic!(),
|
||||||
}
|
|
||||||
_ => panic!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field_expr(expr: Expr, field_name: &str) -> Option<Expr> {
|
fn get_field_expr(expr: Expr, field_name: &str) -> Option<Expr> {
|
||||||
let fields: Punctuated<FieldValue, syn::token::Comma> = match expr {
|
let fields: Punctuated<FieldValue, syn::token::Comma> = match expr {
|
||||||
Expr::Struct(expr) => expr.fields,
|
Expr::Struct(expr) => expr.fields,
|
||||||
_ => panic!("invalid struct")
|
_ => panic!("invalid struct"),
|
||||||
};
|
};
|
||||||
for field in fields {
|
for field in fields {
|
||||||
if let syn::Member::Named(ident) = &field.member {
|
if let syn::Member::Named(ident) = &field.member {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,13 @@
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::intrinsics::transmute;
|
use std::intrinsics::transmute;
|
||||||
|
|
||||||
use libc::*;
|
use ivory_sys::{php_printf, zend_error};
|
||||||
|
|
||||||
use ivory_sys::zend_error;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
pub fn php_printf(format: *const c_char, ...) -> size_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn printf<T: Into<Vec<u8>>>(string: T) {
|
pub fn printf<T: Into<Vec<u8>>>(string: T) {
|
||||||
let cstr = CString::new(string).unwrap();
|
let cstr = CString::new(string).unwrap();
|
||||||
unsafe { php_printf(cstr.as_ptr()); }
|
unsafe {
|
||||||
|
php_printf(cstr.as_ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
|
|
@ -41,5 +37,7 @@ impl From<ErrorLevel> for i32 {
|
||||||
|
|
||||||
pub fn error<T: Into<Vec<u8>>>(level: ErrorLevel, message: T) {
|
pub fn error<T: Into<Vec<u8>>>(level: ErrorLevel, message: T) {
|
||||||
let cstr = CString::new(message).unwrap();
|
let cstr = CString::new(message).unwrap();
|
||||||
unsafe { zend_error(level.into(), cstr.as_ptr()); }
|
unsafe {
|
||||||
|
zend_error(level.into(), cstr.as_ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use libc::*;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
use std::os::raw::{c_int, c_void};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn php_info_print_table_start();
|
pub fn php_info_print_table_start();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! c_str {
|
macro_rules! c_str {
|
||||||
($s:expr) => {{
|
($s:expr) => {{
|
||||||
concat!($s, "\0").as_ptr() as *const ::libc::c_char
|
concat!($s, "\0").as_ptr() as *const ::std::os::raw::c_char
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use std;
|
use std;
|
||||||
|
use std::os::raw::{c_char, c_uchar};
|
||||||
use libc::*;
|
|
||||||
|
|
||||||
use crate::zend::HandlerFunc;
|
use crate::zend::HandlerFunc;
|
||||||
|
|
||||||
|
|
@ -33,7 +32,6 @@ impl ArgInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
fname: *const c_char,
|
fname: *const c_char,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
use std;
|
use std;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::os::raw::{c_char, c_int, c_uchar, c_uint, c_ushort, c_void};
|
||||||
|
|
||||||
use libc::*;
|
use crate::zend::function::{ArgInfo, Function};
|
||||||
|
|
||||||
use crate::zend::function::{Function, ArgInfo};
|
|
||||||
use crate::zend::{ExecuteData, ZVal};
|
use crate::zend::{ExecuteData, ZVal};
|
||||||
|
|
||||||
pub(crate) type StartupFunc = extern "C" fn(type_: c_int, module_number: c_int) -> c_int;
|
pub(crate) type StartupFunc = extern "C" fn(type_: c_int, module_number: c_int) -> c_int;
|
||||||
|
|
@ -34,7 +33,7 @@ pub struct ModuleInternal {
|
||||||
request_shutdown_func: Option<ShutdownFunc>,
|
request_shutdown_func: Option<ShutdownFunc>,
|
||||||
info_func: Option<InfoFunc>,
|
info_func: Option<InfoFunc>,
|
||||||
version: *const c_char,
|
version: *const c_char,
|
||||||
globals_size: size_t,
|
globals_size: usize,
|
||||||
globals_ptr: *const c_void,
|
globals_ptr: *const c_void,
|
||||||
globals_ctor: Option<GlobalsCtorFunc>,
|
globals_ctor: Option<GlobalsCtorFunc>,
|
||||||
globals_dtor: Option<GlobalsDtorFunc>,
|
globals_dtor: Option<GlobalsDtorFunc>,
|
||||||
|
|
@ -97,7 +96,7 @@ impl ModuleInternal {
|
||||||
pub struct FunctionMeta {
|
pub struct FunctionMeta {
|
||||||
pub name: *const c_char,
|
pub name: *const c_char,
|
||||||
pub func: HandlerFunc,
|
pub func: HandlerFunc,
|
||||||
pub args: &'static [ArgInfo]
|
pub args: &'static [ArgInfo],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionMeta {
|
impl FunctionMeta {
|
||||||
|
|
@ -114,5 +113,5 @@ pub struct PhpModule {
|
||||||
pub name: *const c_char,
|
pub name: *const c_char,
|
||||||
pub version: *const c_char,
|
pub version: *const c_char,
|
||||||
pub functions: &'static [HandlerFunc],
|
pub functions: &'static [HandlerFunc],
|
||||||
pub info: &'static [(&'static str, &'static str)]
|
pub info: &'static [(&'static str, &'static str)],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,12 @@
|
||||||
# ivory-sys
|
# ivory-sys
|
||||||
|
|
||||||
Bindings to php.
|
Bindings to php.
|
||||||
|
|
||||||
|
## PHP version
|
||||||
|
|
||||||
|
While building, it will grab the source for the php version specified in `Cargo.toml`.
|
||||||
|
Thus changing the version number of the crate also changes the version of php which it's compiled against
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
This crate is taken almost entirely from [php-sys](https://github.com/hjr3/php-rpm/tree/master/php-sys), all credit goes to it's authors
|
||||||
|
|
@ -26,7 +26,11 @@ fn run_command_or_fail(dir: String, cmd: &str, args: &[&str]) {
|
||||||
args.join(" "),
|
args.join(" "),
|
||||||
dir
|
dir
|
||||||
);
|
);
|
||||||
let ret = Command::new(cmd).current_dir(dir).args(args).env("CC", "clang").status();
|
let ret = Command::new(cmd)
|
||||||
|
.current_dir(dir)
|
||||||
|
.args(args)
|
||||||
|
.env("CC", "clang")
|
||||||
|
.status();
|
||||||
match ret.map(|status| (status.success(), status.code())) {
|
match ret.map(|status| (status.success(), status.code())) {
|
||||||
Ok((true, _)) => return,
|
Ok((true, _)) => return,
|
||||||
Ok((false, Some(c))) => panic!("Command failed with error code {}", c),
|
Ok((false, Some(c))) => panic!("Command failed with error code {}", c),
|
||||||
|
|
@ -69,14 +73,7 @@ fn main() {
|
||||||
|
|
||||||
if !exists("php-src/LICENSE") {
|
if !exists("php-src/LICENSE") {
|
||||||
println_stderr!("Setting up PHP {}", php_version);
|
println_stderr!("Setting up PHP {}", php_version);
|
||||||
run_command_or_fail(
|
run_command_or_fail("/".to_string(), "mkdir", &["-p", &target("")]);
|
||||||
"/".to_string(),
|
|
||||||
"mkdir",
|
|
||||||
&[
|
|
||||||
"-p",
|
|
||||||
&target("")
|
|
||||||
],
|
|
||||||
);
|
|
||||||
run_command_or_fail(
|
run_command_or_fail(
|
||||||
target(""),
|
target(""),
|
||||||
"git",
|
"git",
|
||||||
|
|
@ -159,6 +156,7 @@ fn main() {
|
||||||
.whitelist_function("php_printf")
|
.whitelist_function("php_printf")
|
||||||
.whitelist_type("zval")
|
.whitelist_type("zval")
|
||||||
.whitelist_type("zend_execute_data")
|
.whitelist_type("zend_execute_data")
|
||||||
|
.whitelist_type("zend_module_entry")
|
||||||
.derive_default(false)
|
.derive_default(false)
|
||||||
.header("wrapper.h")
|
.header("wrapper.h")
|
||||||
.generate()
|
.generate()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,5 @@
|
||||||
#define PHP_RS_WRAPPER_H
|
#define PHP_RS_WRAPPER_H
|
||||||
#include <Zend/zend.h>
|
#include <Zend/zend.h>
|
||||||
#include <Zend/zend_compile.h>
|
#include <Zend/zend_compile.h>
|
||||||
//#include <main/php.h>
|
#include <main/php.h>
|
||||||
//#include <sapi/embed/php_embed.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue