Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.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
从Rust FFI访问DPDK中的静态C函数_C_Rust_Ffi_Dpdk - Fatal编程技术网

从Rust FFI访问DPDK中的静态C函数

从Rust FFI访问DPDK中的静态C函数,c,rust,ffi,dpdk,C,Rust,Ffi,Dpdk,我是一个相当新手的程序员,我遇到了一个我认为我理解但不知道如何解决的问题。我正在尝试使用Rust FFI与C中的所有内容进行交互。我的第一次尝试是重新创建helloworld示例应用程序 我遇到了一个编译错误,我认为这是由于DPDK中的函数是静态的,不能直接从库中获得。我的FFI界面在这里: use libc::{c_uint, c_int, c_void, c_char}; pub type LcoreFunctionT = extern "C" fn(arg1: *mut c_vo

我是一个相当新手的程序员,我遇到了一个我认为我理解但不知道如何解决的问题。我正在尝试使用Rust FFI与C中的所有内容进行交互。我的第一次尝试是重新创建helloworld示例应用程序

我遇到了一个编译错误,我认为这是由于DPDK中的函数是静态的,不能直接从库中获得。我的FFI界面在这里:

use libc::{c_uint, c_int, c_void, c_char};

pub type LcoreFunctionT =
    extern "C" fn(arg1: *mut c_void) -> c_int;

extern {
    pub fn rte_eal_init(argc: c_int,
                        argv: *mut *mut c_char) -> c_int;
    pub fn rte_eal_remote_launch(f: *mut LcoreFunctionT,
                                    arg: *mut c_void,
                                    slave_id: c_uint) -> c_int;
    pub fn rte_eal_mp_wait_lcore() -> ();
    pub fn rte_lcore_id() -> c_uint;
    pub fn rte_get_next_lcore(i: c_uint,
                                skip_master: c_int,
                                wrap: c_int) -> c_uint;
}
我还有一个库引用了这个函数并包装了函数:

extern crate libc;

use libc::{c_uint, c_int, c_char, c_void};
use std::ffi::CString;
use std::ptr;

mod ffi_rte_eal;

pub fn dpdk_rte_eal_init(argc: i32, argv: Vec<String>) -> i32 {
    let mut args: Vec<*mut c_char> =
        argv.iter().map(|x| CString::new(x.clone()).unwrap().into_raw()).collect();
    let retc: c_int = unsafe {ffi_rte_eal::rte_eal_init(argc as c_int, args.as_mut_ptr())};
    let ret: i32 = retc as i32;
    ret
}

pub fn dpdk_rte_eal_remote_launch(f: extern "C" fn(*mut c_void) -> i32,
                                    slave_id: u32 ) -> i32 {
    let mut fc: ffi_rte_eal::LcoreFunctionT = f;
    let retc: c_int = unsafe {ffi_rte_eal::rte_eal_remote_launch(&mut fc,
                                                                ptr::null_mut() as *mut c_void,
                                                                slave_id as c_uint)};
    let ret: i32 = retc as i32;
    ret
}

pub fn dpdk_rte_eal_mp_wait_lcore() -> (){
    unsafe {
        ffi_rte_eal::rte_eal_mp_wait_lcore();
    }
}

pub fn dpdk_rte_lcore_id() -> u32 {
    let retc: c_uint = unsafe {ffi_rte_eal::rte_lcore_id()};
    let ret: u32 = retc as u32;
    ret
}

pub fn dpdk_rte_get_next_lcore(i: u32,
                                skip_master: i32,
                                wrap: i32) -> u32 {
    let retc: c_uint = unsafe {ffi_rte_eal::rte_get_next_lcore(i as c_uint,
                                                               skip_master as c_int,
                                                               wrap as c_int)};
    let ret: u32 = retc as u32;
    ret
}
当我试图针对FFI接口编译我自己的应用程序时,我不断收到有关未定义引用
rte\u lcore\u id
rte\u get\u next\u lcore
的错误。根据DPDK的API文档,这些函数是liberte_eal库的一部分,但不是。我假设这些是静态函数,我将无法从锈迹中看到它们

在与DPDK捆绑的helloworld示例应用程序中,他们直接导入rte_lcore.h。我认为这就是为什么他们可以访问这些函数而不只是引用liberte_eal


是否有一种方法可以访问Rust中的此文件,或者必须有类似于C中的垫片的东西,让我包装这些函数并通过FFI使其可用?

正如您可以看到的那样,如果打开相应的头文件,这些函数将直接在那里声明。这意味着这些函数将包含在包含此头的每个
.c
/
.cpp
文件中,但由于它们是
静态的
,链接器不会为它们创建符号,因此它们实际上不存在于库的编译版本中。描述了为什么可能需要这样做,但不幸的是,这种设计对外国金融机构不太友好

您可以做的是创建一个存根C库,其中包含完全相同的函数,这些函数从头部委托给静态函数,但它们本身不是静态的。像这样:

#include <rte_lcore.h>

unsigned my_rte_lcore_count(void) {
    return rte_lcore_count();
}

// and so forth for every function you need
我认为没有比这更简单、更正确的方法了


更新:哦,我没有注意到你问题中的最后一句话。是的,你说得对,写这样一个垫片是正确的方法。

很棘手。正如您推测的那样,
静态
函数的问题在于它们不应该在当前编译单元之外使用,因此即使没有内联,它们的符号也可能是私有的(并且在库之外无法访问)。您认为函数调用开销/缺少内联与在
safe
Rust中重写函数相比可能会对性能产生负面影响吗?这是有道理的。我曾想过要像你提到的那样编写存根库,但不知道这是否是“正确”的方法。还在学习。@MatthieuM.,这自然很大程度上取决于这些函数的使用方式。如果它们很少被调用,我认为这实际上是像
core\u count()
这样的函数的情况,应该不会有任何明显的影响。@MatthieuM.,我还看到这些函数,至少其中一些函数,调用了其他C宏,所以我认为仍然可能需要一些垫片来正确扩展这些宏,即使你在Rust中重新实现了它们。多亏了Vladimir,我能够建立一个简单的存根文件库,现在一切都正常了。我感谢你的回应!
#include <rte_lcore.h>

unsigned my_rte_lcore_count(void) {
    return rte_lcore_count();
}

// and so forth for every function you need