簡體   English   中英

從Rust FFI訪問DPDK中的靜態C函數

[英]Accessing static C functions in DPDK from Rust FFI

我是一個相當新手的程序員,我遇到了一個我認為我理解但不知道如何修復的問題。 我正在嘗試使用Rust FFI與英特爾的DPDK進行交互,這完全在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
}

以及用於鏈接庫的build.rs文件 -

//build.rs

fn main() {
    println!("cargo:rustc-link-lib=static=rte_eal");
    println!("cargo:rustc-link-search=native=/usr/local/lib");
    println!("cargo:rustc-link-lib=static=rte_mempool");
    println!("cargo:rustc-link-search=native=/usr/local/lib");
    println!("cargo:rustc-link-lib=static=rte_ring");
    println!("cargo:rustc-link-search=native=/usr/local/lib");
}

當我嘗試針對FFI接口編譯自己的應用程序時,我不斷收到有關rte_lcore_idrte_get_next_lcore未定義引用的錯誤。 根據DPDK的API文檔,這些函數是librte_eal庫的一部分,但在rte_lcore.h定義為靜態函數 我假設這些是靜態函數,我將無法從Rust中看到它們。

在與DPDK捆綁在一起的helloworld示例應用程序中,它們直接導入rte_lcore.h。 我認為這就是為什么他們可以在不引用librte_eal的情況下訪問這些功能?

是否有一種方法可以在Rust中訪問它,或者在C中是否需要像墊片這樣的東西來包裝這些函數並通過FFI使它們可用?

如您所見,如果打開相應的頭文件,則會直接在那里聲明這些函數。 這意味着這些函數將包含在包含此標頭的每個 .c / .cpp文件中,但由於它們是static ,鏈接器不會為它們創建符號,因此它們實際上不存在於編譯版本中。圖書館。 這里描述了為什么需要這樣做,但遺憾的是這種設計對FFI不是很友好。

你可以做的是創建一個存根C庫,它包含完全相同的函數,這些函數從頭部委托給靜態函數,但它們本身不是靜態的。 像這樣:

#include <rte_lcore.h>

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

// and so forth for every function you need

然后,您可以使用自定義編寫的Makefile或Cargo構建腳本將此存根文件編譯為靜態庫,並將最終程序鏈接到該文件。 那么,當然,您應該在extern塊中編寫這些函數,而不是原始函數:

extern {
    fn my_rte_lcore_count() -> libc::c_uint;
}

我認為沒有更簡單,更正確的方法。

更新:哦,我沒有注意到你在問題中的最后一句話。 是的,你是對的,寫這樣的墊片是正確的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM