mirror of
https://github.com/icewind1991/ivory.git
synced 2026-06-03 10:44:09 +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::zend::{ExecuteData, Value};
|
||||
|
||||
#[ivory_export]
|
||||
fn hello_other(_other: String) {
|
||||
printf(format!("Hello ",));
|
||||
}
|
||||
|
||||
#[ivory_export]
|
||||
fn hello_world() {
|
||||
printf("Hello world, Rust!");
|
||||
|
|
@ -10,6 +15,6 @@ fn hello_world() {
|
|||
ivory_module!({
|
||||
name: "demo",
|
||||
version: "0.0.1",
|
||||
functions: &[hello_world],
|
||||
functions: &[hello_world, hello_other],
|
||||
info: &[("demo extension", "enabled")]
|
||||
});
|
||||
|
|
@ -2,17 +2,14 @@
|
|||
|
||||
extern crate proc_macro;
|
||||
|
||||
use core::fmt::Debug;
|
||||
use std::collections::HashMap;
|
||||
use std::process::Command;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use proc_macro2::{Span, TokenStream, TokenTree};
|
||||
use proc_macro2::token_stream::IntoIter;
|
||||
use quote::{quote, quote_spanned};
|
||||
use syn::{
|
||||
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::{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};
|
||||
use syn::parse_quote::parse;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
|
|
@ -48,6 +45,12 @@ fn export_fn(item: ItemFn) -> TokenStream {
|
|||
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! {
|
||||
#[no_mangle]
|
||||
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{
|
||||
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
|
||||
#[proc_macro]
|
||||
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 {
|
||||
TokenTree::Ident(ident) => {
|
||||
ident.to_string()
|
||||
},
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
}).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 {
|
||||
let definitions = names.into_iter().map(|name| {
|
||||
// TODO: args
|
||||
//let meta_name = Ident::new(&format!("FUNCTION_META_{}", name.to_uppercase()), span);
|
||||
let func_ident = Ident::new(&name, span);
|
||||
let meta_name = Ident::new(&format!("FUNCTION_META_{}", name.to_uppercase()), span);
|
||||
quote! {
|
||||
::ivory::zend::Function::new(::ivory::c_str!(#name), #func_ident),
|
||||
#meta_name.as_function()
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use std;
|
||||
|
||||
use libc::*;
|
||||
|
||||
use crate::zend::HandlerFunc;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
pub struct ArgInfo {
|
||||
name: *const c_char,
|
||||
|
|
@ -14,7 +16,7 @@ pub struct ArgInfo {
|
|||
}
|
||||
|
||||
impl ArgInfo {
|
||||
pub fn new(
|
||||
pub const fn new(
|
||||
name: *const c_char,
|
||||
allow_null: bool,
|
||||
is_variadic: bool,
|
||||
|
|
@ -31,6 +33,7 @@ impl ArgInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
pub struct Function {
|
||||
fname: *const c_char,
|
||||
|
|
@ -54,14 +57,16 @@ impl Function {
|
|||
pub fn new_with_args(
|
||||
name: *const c_char,
|
||||
handler: HandlerFunc,
|
||||
mut args: Vec<ArgInfo>,
|
||||
mut args: &'static [ArgInfo],
|
||||
) -> Function {
|
||||
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);
|
||||
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 {
|
||||
fname: name,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ use std::mem;
|
|||
|
||||
use libc::*;
|
||||
|
||||
use crate::zend::function::Function;
|
||||
use std::ffi::{CString, CStr};
|
||||
use crate::zend::function::{Function, ArgInfo};
|
||||
|
||||
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;
|
||||
|
|
@ -100,12 +99,17 @@ impl ModuleInternal {
|
|||
|
||||
pub struct FunctionMeta {
|
||||
pub name: *const c_char,
|
||||
pub arg_names: &'static [*const c_char]
|
||||
pub func: HandlerFunc,
|
||||
pub args: &'static [ArgInfo]
|
||||
}
|
||||
|
||||
impl FunctionMeta {
|
||||
pub fn into_function(self, func: HandlerFunc) -> Function {
|
||||
Function::new(self.name, func)
|
||||
pub fn as_function(&self) -> Function {
|
||||
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