Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
原始指针将null从Rust传递到C_C_Rust_Ffi - Fatal编程技术网

原始指针将null从Rust传递到C

原始指针将null从Rust传递到C,c,rust,ffi,C,Rust,Ffi,我试图从rust中的C函数上检索一个原始指针,并将该原始指针用作另一个库中另一个C函数的参数。当我传递原始指针时,我在C端得到一个空指针 我曾试图对我的问题进行简化,但当我这样做时,它的效果正如我所期望的那样- C代码- struct MyStruct { int value; }; struct MyStruct * get_struct() { struct MyStruct * priv_struct = (struct MyStruct*) malloc( sizeof

我试图从rust中的C函数上检索一个原始指针,并将该原始指针用作另一个库中另一个C函数的参数。当我传递原始指针时,我在C端得到一个空指针

我曾试图对我的问题进行简化,但当我这样做时,它的效果正如我所期望的那样-

C代码-

struct MyStruct {
    int value;
};

struct MyStruct * get_struct() {
    struct MyStruct * priv_struct = (struct MyStruct*) malloc( sizeof(struct MyStruct));

    priv_struct->value = 0;
    return priv_struct;
}

void put_struct(struct MyStruct *priv_struct) {
    printf("Value - %d\n", priv_struct->value);
}
锈代码-

#[repr(C)]
struct MyStruct {
    value: c_int,
}

extern {
    fn get_struct() -> *mut MyStruct;
}

extern {
    fn put_struct(priv_struct: *mut MyStruct) -> ();
}

fn rust_get_struct() -> *mut MyStruct {
    let ret = unsafe { get_struct() };
    ret
}

fn rust_put_struct(priv_struct: *mut MyStruct) {
    unsafe { put_struct(priv_struct) };
}

fn main() {
    let main_struct = rust_get_struct();
    rust_put_struct(main_struct);
}
当我运行这个时,我得到值-0的输出

~/Dev/rust_test$ sudo ./target/debug/rust_test 
Value - 0
~/Dev/rust_test$
然而,当尝试对DPDK库执行此操作时,我以相同的方式检索并传递原始指针,但得到一个segfault。如果我使用gdb进行调试,我可以看到我在Rust端传递一个指针,但在C端看到它为NULL-

(gdb)第0帧
#0 rte_eth_rx_queue_设置(端口id=0'\000',rx_queue_id=,nb_rx_desc=,套接字id=0,rx_conf=0x0,mp=0x0)
at/home/kenton/Dev/dpdk-16.07/lib/librte_ether/rte_ethdev.c:1216
1216如果(mp->private_data_size
在第1帧中,mb有一个地址,正在被传递。在第0帧中,库中的接收函数将其显示为0x0,表示mp

我的代码接收指针-

let mb = dpdk_rte_pktmbuf_pool_create(CString::new("MBUF_POOL").unwrap().as_ptr(),
       (8191 * nb_ports) as u32 , 250, 0, 2176, dpdk_rte_socket_id());
这将调用ffi库-

pub fn dpdk_rte_pktmbuf_pool_create(name: *const c_char,
                               n: u32,
                               cache_size: u32,
                               priv_size: u16,
                               data_room_size: u16,
                               socket_id: i32) -> *mut rte_mempool::ffi::RteMempool {
    let ret: *mut rte_mempool::ffi::RteMempool = unsafe {
        ffi::shim_rte_pktmbuf_pool_create(name,
                                          n as c_uint,
                                          cache_size as c_uint,
                                          priv_size as uint16_t,
                                          data_room_size as uint16_t,
                                          socket_id as c_int)
    };
    ret
}
外国金融机构-

extern {
    pub fn shim_rte_pktmbuf_pool_create(name: *const c_char,
                                        n: c_uint,
                                        cache_size: c_uint,
                                        priv_size: uint16_t,
                                        data_room_size: uint16_t,
                                        socket_id: c_int) -> *mut rte_mempool::ffi::RteMempool;
}
extern {
    pub fn rte_eth_rx_queue_setup(port_id: uint8_t,
                              rx_queue_id: uint16_t,
                              nb_tx_desc: uint16_t,
                              socket_id: c_uint,
                              rx_conf: Option<*const RteEthRxConf>,
                              mb: *mut rte_mempool::ffi::RteMempool ) -> c_int;
}
C功能-

struct rte_mempool *
rte_pktmbuf_pool_create(const char *name, unsigned n,
    unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
    int socket_id);
ret = dpdk_rte_eth_rx_queue_setup(port,q,128,0,None,mb);
当我传递指针时,它看起来与上面的简化版本基本相同。我的变量mb包含一个原始指针,我将它传递给另一个函数-

struct rte_mempool *
rte_pktmbuf_pool_create(const char *name, unsigned n,
    unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
    int socket_id);
ret = dpdk_rte_eth_rx_queue_setup(port,q,128,0,None,mb);
外国金融机构图书馆-

pub fn dpdk_rte_eth_rx_queue_setup(port_id: u8,
                                   rx_queue_id: u16,
                                   nb_tx_desc: u16,
                                   socket_id: u32,
                                   rx_conf: Option<*const ffi::RteEthRxConf>,
                                   mb_pool: *mut rte_mempool::ffi::RteMempool ) -> i32 {
    let retc: c_int = unsafe {ffi::rte_eth_rx_queue_setup(port_id as uint8_t,
                                                          rx_queue_id as uint16_t,
                                                          nb_tx_desc as uint16_t,
                                                          socket_id as c_uint,
                                                          rx_conf,
                                                          mb)};
    let ret: i32 = retc as i32;
    ret
}
很抱歉长度太长,但我觉得我遗漏了一些简单的东西,无法解决。我已经检查了传递的每个字段的结构对齐方式,甚至看到了预期收到的指针值-

(gdb)第1帧
#1 0x00005555568DCF4在dpdk::ethdev::dpdk_rte_eth_rx_queue_设置中(端口id=0'\000',rx_queue_id=0,nb_tx_desc=128,套接字id=0,rx_conf=None,
mb=0x7fff3fe47640)位于/home/kenton/Dev/dpdk_ffi/src/ethdev/mod.rs:32
32让retc:c_int=unsafe{ffi::rte_eth_rx_queue_设置(端口id为uint8_t,
(gdb)打印*mb
$1=RteMempool={name=“MBUF_POOL”,'\000',POOL_union=PoolUnionStruct={data=140734245862912},POOL_config=0x0,
mz=0x7ffff7fa4c68,标志=16,套接字id=0,大小=8191,缓存大小=250,elt大小=2304,头大小=64,尾大小=0,
私有数据大小=64,操作索引=0,本地缓存=0x7fff3fe47700,填充大小=8191,elt列表=RTEMPOOLOBJHDRLIST={
stqh_first=0x7fff3ebc7f68,stqh_last=0x7fff3fe46ce8},nb_mem_chunks=1,mem_list=rtempoolmemhdrlist={stqh_first=0x7fff3ebb7d80,
stqh_last=0x7fff3ebb7d80},_align=0x7fff3fe47700}
关于指针为什么在C端变为NULL,你有什么想法吗?

CString::new(“…”).unwrap().as_ptr()
不起作用。
CString
是临时的,因此
as_ptr()
调用返回临时的内部指针,当你使用它时,它可能会挂起。这是“安全的”根据Rust的安全定义,只要不使用指针,但最终会在
不安全的
块中使用指针。应将字符串绑定到变量,并在该变量上使用
as_ptr

这是一个如此普遍的问题,甚至有


另外,原始指针本身是可以为空的,因此与
const struct rte_eth_rxconf*
等效的Rust FFI将是
*const FFI::rtethrxconf
,而不是
Option

如何分别运行这两个程序?或者从另一个程序运行一个程序?
CString::new(“MBUF\u POOL”).unwrap().as\u ptr()
看起来很危险。你确定你从中得到的原始指针足够长吗?TBH,我不知道这个
CString
是什么时候被删除的。如果它是在调用
dpdk_rte_pktmbuf_pool_create
函数之前被删除的,指针将无效。你真的应该避免写“safe”像dpdk_rte_pktmbuf_pool_这样的包装器为FFI函数创建了一个真正不安全的包装器!如果有一个警告的话……或者当我们这样做的时候。(免责声明:我是一个Clippy dev)谢谢你的信息,我已经把它改成这样-
让name=CString::new(“MBUF_pool”)。unwrap()
让mb=dpdk::rte_mbuf::dpdk_rte_pktmbuf_pool_创建(name.as_ptr(),(8191*nb_端口)为u32、250、0、2176,dpdk::rte_eal::dpdk_rte_socket_id())
但是,我仍然得到相同的行为。我尝试传递一个指向包含“mbuf_pool”的结构的指针字符串,但在C端结果为NULL。我不确定
选项
在FFI中是否有意义。请删除该选项。接受该选项的C函数接受指向结构的指针或NULL。是否有方法将NULL传递给C而不使用选项和无?