mirror of
https://github.com/icewind1991/ivory.git
synced 2026-06-03 18:54:07 +02:00
args relfection
This commit is contained in:
parent
224c648852
commit
1e6e05c135
4 changed files with 54 additions and 21 deletions
|
|
@ -2,6 +2,11 @@ use ivory::*;
|
||||||
use ivory::externs::printf;
|
use ivory::externs::printf;
|
||||||
use ivory::zend::{ExecuteData, Value};
|
use ivory::zend::{ExecuteData, Value};
|
||||||
|
|
||||||
|
#[ivory_export]
|
||||||
|
fn hello_other(_other: String) {
|
||||||
|
printf(format!("Hello ",));
|
||||||
|
}
|
||||||
|
|
||||||
#[ivory_export]
|
#[ivory_export]
|
||||||
fn hello_world() {
|
fn hello_world() {
|
||||||
printf("Hello world, Rust!");
|
printf("Hello world, Rust!");
|
||||||
|
|
@ -10,6 +15,6 @@ fn hello_world() {
|
||||||
ivory_module!({
|
ivory_module!({
|
||||||
name: "demo",
|
name: "demo",
|
||||||
version: "0.0.1",
|
version: "0.0.1",
|
||||||
functions: &[hello_world],
|
functions: &[hello_world, hello_other],
|
||||||
info: &[("demo extension", "enabled")]
|
info: &[("demo extension", "enabled")]
|
||||||
});
|
});
|
||||||
|
|
@ -2,17 +2,14 @@
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use core::fmt::Debug;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use core::fmt::Debug;
|
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream, TokenTree};
|
use proc_macro2::{Span, TokenStream, TokenTree};
|
||||||
use proc_macro2::token_stream::IntoIter;
|
use proc_macro2::token_stream::IntoIter;
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
use syn::{
|
use syn::{Attribute, AttributeArgs, Data, Expr, ExprStruct, Fields, FieldValue, FnArg, Ident, Item, ItemFn, Lit, LitStr, Meta, parse2, parse_macro_input, parse_quote, parse_str, Pat, Path, Type};
|
||||||
Attribute, AttributeArgs, Data, Expr, ExprStruct, Fields, FieldValue, Ident, Item, ItemFn, Lit, LitStr,
|
|
||||||
Meta, parse2, parse_macro_input, parse_quote, parse_str, Pat, Path,
|
|
||||||
};
|
|
||||||
use syn::parse_quote::parse;
|
use syn::parse_quote::parse;
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
|
@ -48,6 +45,12 @@ fn export_fn(item: ItemFn) -> TokenStream {
|
||||||
unimplemented!("generics are not supported for exported functions");
|
unimplemented!("generics are not supported for exported functions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let arg_defs = decl.inputs.into_iter()
|
||||||
|
.map(get_arg_info)
|
||||||
|
.map(|(name, _type, is_ref)| {
|
||||||
|
quote!(::ivory::zend::ArgInfo::new(::ivory::c_str!(#name), false, false, #is_ref))
|
||||||
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn #name(data: &ExecuteData, retval: &Value) {
|
pub extern "C" fn #name(data: &ExecuteData, retval: &Value) {
|
||||||
|
|
@ -55,11 +58,29 @@ 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 ::libc::c_char},
|
||||||
|
func: #name,
|
||||||
|
args: &[ #(#arg_defs),*]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_arg_info(arg: FnArg) -> (String, Type, bool) {
|
||||||
|
match arg {
|
||||||
|
FnArg::Captured(cap) => {
|
||||||
|
let arg_type = cap.ty;
|
||||||
|
match cap.pat {
|
||||||
|
Pat::Ident(ident_pat) => {
|
||||||
|
(ident_pat.ident.to_string(), arg_type, ident_pat.by_ref.is_some())
|
||||||
|
},
|
||||||
|
Pat::Ref(ref_pat) => unimplemented!(),
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => panic!("only normal function arguments are supported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// See the [crate documentation](index.html) for details
|
/// See the [crate documentation](index.html) for details
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn ivory_module(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn ivory_module(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
|
@ -162,7 +183,7 @@ fn get_function_names(struct_def: TokenStream) -> Vec<String> {
|
||||||
match tree {
|
match tree {
|
||||||
TokenTree::Ident(ident) => {
|
TokenTree::Ident(ident) => {
|
||||||
ident.to_string()
|
ident.to_string()
|
||||||
},
|
}
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
}
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
|
|
@ -192,11 +213,9 @@ fn get_field_expr(expr: Expr, field_name: &str) -> Option<Expr> {
|
||||||
|
|
||||||
fn get_funcs(names: Vec<String>, span: Span) -> TokenStream {
|
fn get_funcs(names: Vec<String>, span: Span) -> TokenStream {
|
||||||
let definitions = names.into_iter().map(|name| {
|
let definitions = names.into_iter().map(|name| {
|
||||||
// TODO: args
|
let meta_name = Ident::new(&format!("FUNCTION_META_{}", name.to_uppercase()), span);
|
||||||
//let meta_name = Ident::new(&format!("FUNCTION_META_{}", name.to_uppercase()), span);
|
|
||||||
let func_ident = Ident::new(&name, span);
|
|
||||||
quote! {
|
quote! {
|
||||||
::ivory::zend::Function::new(::ivory::c_str!(#name), #func_ident),
|
#meta_name.as_function()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use std;
|
use std;
|
||||||
|
|
||||||
use libc::*;
|
use libc::*;
|
||||||
|
|
||||||
use crate::zend::HandlerFunc;
|
use crate::zend::HandlerFunc;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct ArgInfo {
|
pub struct ArgInfo {
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
|
|
@ -14,7 +16,7 @@ pub struct ArgInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArgInfo {
|
impl ArgInfo {
|
||||||
pub fn new(
|
pub const fn new(
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
allow_null: bool,
|
allow_null: bool,
|
||||||
is_variadic: bool,
|
is_variadic: bool,
|
||||||
|
|
@ -31,6 +33,7 @@ impl ArgInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
fname: *const c_char,
|
fname: *const c_char,
|
||||||
|
|
@ -54,14 +57,16 @@ impl Function {
|
||||||
pub fn new_with_args(
|
pub fn new_with_args(
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
handler: HandlerFunc,
|
handler: HandlerFunc,
|
||||||
mut args: Vec<ArgInfo>,
|
mut args: &'static [ArgInfo],
|
||||||
) -> Function {
|
) -> Function {
|
||||||
let num_args = args.len() as u32;
|
let num_args = args.len() as u32;
|
||||||
|
let mut args_vec = Vec::new();
|
||||||
|
|
||||||
let arg_count = ArgInfo::new(num_args as *const c_char, false, false, false);
|
let arg_count = ArgInfo::new(num_args as *const c_char, false, false, false);
|
||||||
args.insert(0, arg_count);
|
args_vec.push(arg_count);
|
||||||
|
args_vec.extend_from_slice(args);
|
||||||
|
|
||||||
let arg_ptr = Box::into_raw(args.into_boxed_slice()) as *const ArgInfo;
|
let arg_ptr = Box::into_raw(args_vec.into_boxed_slice()) as *const ArgInfo;
|
||||||
|
|
||||||
Function {
|
Function {
|
||||||
fname: name,
|
fname: name,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@ use std::mem;
|
||||||
|
|
||||||
use libc::*;
|
use libc::*;
|
||||||
|
|
||||||
use crate::zend::function::Function;
|
use crate::zend::function::{Function, ArgInfo};
|
||||||
use std::ffi::{CString, CStr};
|
|
||||||
|
|
||||||
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;
|
||||||
pub(crate) type ShutdownFunc = extern "C" fn(type_: c_int, module_number: c_int) -> c_int;
|
pub(crate) type ShutdownFunc = extern "C" fn(type_: c_int, module_number: c_int) -> c_int;
|
||||||
|
|
@ -100,12 +99,17 @@ impl ModuleInternal {
|
||||||
|
|
||||||
pub struct FunctionMeta {
|
pub struct FunctionMeta {
|
||||||
pub name: *const c_char,
|
pub name: *const c_char,
|
||||||
pub arg_names: &'static [*const c_char]
|
pub func: HandlerFunc,
|
||||||
|
pub args: &'static [ArgInfo]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionMeta {
|
impl FunctionMeta {
|
||||||
pub fn into_function(self, func: HandlerFunc) -> Function {
|
pub fn as_function(&self) -> Function {
|
||||||
Function::new(self.name, func)
|
if self.args.len() == 0 {
|
||||||
|
Function::new(self.name, self.func)
|
||||||
|
} else {
|
||||||
|
Function::new_with_args(self.name, self.func, self.args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue