繁体   English   中英

如何在Rust中将整数转换为C中的char *

[英]How do you cast integer in Rust to char* in C

我有以下用例。 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端(执行代码时),该值在每次执行时都是完全随机的。 我想问的是,与C端的( (const char*)(unsigned long int)(1) )相比,我投射i8的方式是否正确?

----编辑-----

一些更多的细节。 生成的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;

这是在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,
}

您的代码将整数转换为指针-正如Stargateur在评论中所说,正确的实现方式是required_args as *const ::std::os::raw::c_char

相反,您要使用Box::new在堆上分配required_args ,然后使用into_raw将其移出内存管理器的手-给出指向required_args值的指针,直到您手动将其清除为止永远。

这似乎适用于以下测试

因为您通过执行*arguments[0].name将指针解引用到堆中,所以该指针的值确实为5

不幸的是,在PHP端(执行代码时),该值在每次执行时都是完全随机的。

这不足为奇。 由于代码的最终结果是该字段的值只是指向堆的某个指针,因此每次您运行代码时,它的值都会改变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM