1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
use super::libperl_sys::*; use std::ptr; use std::ffi::{CString}; use std::os::raw::{c_char, c_int}; use std::env; pub struct Perl { debug: bool, args: Vec<CString>, env: Vec<CString>, pub my_perl: *mut PerlInterpreter, } impl Drop for Perl { fn drop(&mut self) { if self.debug { println!("destructuring my perl"); } unsafe { perl_destruct(self.my_perl) }; } } extern "C" { #[cfg(perl_useithreads)] fn boot_DynaLoader(perl: *mut PerlInterpreter, cv: *mut CV); #[cfg(not(perl_useithreads))] fn boot_DynaLoader(cv: *mut CV); } #[allow(non_camel_case_types)] #[cfg(perl_useithreads)] type xsinit_type = extern "C" fn(*mut PerlInterpreter) -> (); #[allow(non_camel_case_types)] #[cfg(not(perl_useithreads))] type xsinit_type = extern "C" fn() -> (); #[allow(non_snake_case)] #[cfg(perl_useithreads)] pub fn newXS(perl: *mut PerlInterpreter, name: &str, xsub: XSUBADDR_t, filename: &str) -> *mut CV { let name = CString::new(name).unwrap(); let filename = CString::new(filename).unwrap(); unsafe {Perl_newXS(perl, name.as_ptr(), xsub, filename.as_ptr())} } #[allow(non_snake_case)] #[cfg(not(perl_useithreads))] pub fn newXS(name: &str, xsub: XSUBADDR_t, filename: &str) -> *mut CV { let name = CString::new(name).unwrap(); let filename = CString::new(filename).unwrap(); unsafe {Perl_newXS(name.as_ptr(), xsub, filename.as_ptr())} } #[cfg(perl_useithreads)] pub extern "C" fn xs_init(perl: *mut PerlInterpreter) { newXS(perl, "DynaLoader::boot_DynaLoader", Some(boot_DynaLoader), file!()); } #[cfg(not(perl_useithreads))] pub extern "C" fn xs_init() { newXS("DynaLoader::boot_DynaLoader", Some(boot_DynaLoader), file!()); } impl Perl { pub fn new() -> Perl { let perl = unsafe {perl_alloc()}; unsafe {perl_construct(perl)}; return Perl { args: Vec::new(), env: Vec::new(), my_perl: perl, debug: false, } } pub fn parse(&mut self, args: &[&str], envp: &[&str]) -> i32 { self.args = args.iter().map(|&arg| CString::new(arg).unwrap()) .collect::<Vec<CString>>(); self.env = envp.iter().map(|&arg| CString::new(arg).unwrap()) .collect::<Vec<CString>>(); self.perl_parse_1() } pub fn parse_env_args(&mut self, args: env::Args, envp: env::Vars) -> i32 { self.args = args.map(|arg| CString::new(arg).unwrap()) .collect::<Vec<CString>>(); self.env = envp.map(| (key, value) | CString::new( String::from(&[key, value].join("=")) ).unwrap()).collect::<Vec<CString>>(); self.perl_parse_1() } fn perl_parse_1(&mut self) -> i32 { unsafe { perl_parse( self.my_perl, Some(xs_init as xsinit_type), self.args.len() as c_int, make_argv_from_vec(&self.args) .as_ptr() as *mut *mut c_char, ensure_terminating_null(make_argv_from_vec(&self.env)) .as_ptr() as *mut *mut c_char, ) } } #[cfg(all(perlapi_ver26,perl_useithreads))] pub fn op_class(&self, o: *const OP) -> OPclass { unsafe {Perl_op_class(self.my_perl, o)} } #[cfg(all(perlapi_ver26,not(perl_useithreads)))] pub fn op_class(&self, o: *const OP) -> OPclass { unsafe {Perl_op_class(o)} } } pub fn make_argv_from_vec(args: &Vec<CString>) -> Vec<*mut c_char> { args.iter().map(|arg| arg.as_ptr() as *mut c_char) .collect::<Vec<*mut c_char>>() } pub fn ensure_terminating_null(mut args: Vec<*mut c_char>) -> Vec<*mut c_char> { if args.len() == 0 || args.last() != None { args.push(ptr::null_mut()); } args }