У меня есть следующий вариант использования.Структура в C выглядит следующим образом:
typedef struct _zend_internal_arg_info {
const char *name;
zend_type type;
zend_uchar pass_by_reference;
zend_bool is_variadic;
} zend_internal_arg_info;
Обычно поле name
содержит имя функции.Но из-за внутренней реализации это поле также может содержать целое число.На C-конце есть макрос, выполняющий приведение типа:
(const char*)(unsigned long int)(1)
То, что я хочу сделать, - это выполнить то же приведение на конце Rust.В итоге я получил следующий код:
fn create_null_argument(required_args: u8, return_reference: bool) -> ZendFunctionArgument {
let required_args_ref = Box::into_raw(Box::new(required_args as i8)) as *const i8;
ZendFunctionArgument {
arg: php_bindings::_zend_internal_arg_info {
name: required_args_ref,
type_: 0,
pass_by_reference: if return_reference { 1 } else { 0 },
is_variadic: 0,
},
}
}
Кажется, это работает со следующим тестом:
let arguments_ptr = ZendFunctionArguments::new(5, true).into_raw();
unsafe {
let arguments: Vec<php_bindings::_zend_internal_arg_info> = Vec::from_raw_parts(arguments_ptr as *mut _, 1, 1);
let required_args = *arguments[0].name;
assert_eq!(5, required_args);
}
К сожалению, в конце PHP (когда код выполняется) значение полностьюслучайным образом при каждом исполнении.Здесь я хочу спросить, правильный ли способ кастовки i8 по сравнению с кастингом на C-конце ((const char*)(unsigned long int)(1)
)?
---- EDIT -----
Еще немного подробностей.Сгенерированное связывание PHP:
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _zend_internal_arg_info {
pub name: *const ::std::os::raw::c_char,
pub type_: zend_type,
pub pass_by_reference: zend_uchar,
pub is_variadic: zend_bool,
}
Вот неиспользуемая структура с некоторым описанием этой искаженной логики:
/* the following structure repeats the layout of zend_internal_arg_info,
* but its fields have different meaning. It's used as the first element of
* arg_info array to define properties of internal functions.
* It's also used for the return type.
*/
typedef struct _zend_internal_function_info {
zend_uintptr_t required_num_args;
zend_type type;
zend_bool return_reference;
zend_bool _is_variadic;
} zend_internal_function_info;
Вот весь макрос beig, используемый в c:
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), 0, return_reference, 0 },
И zend_uintptr_t
- это:
typedef uintptr_t zend_uintptr_t;
, а затем:
typedef unsigned long int uintptr_t;
и структура:
pub struct ZendFunctionArgument {
arg: php_bindings::_zend_internal_arg_info,
}