I'm a fairly novice programmer and I'm running into a problem that I think I understand but don't know how to fix. I'm attempting to use the Rust FFI to interact with Intel's DPDK which is all in C. My first attempt at this is recreating the helloworld example app.
I'm reaching a compilation error that I think is due to functions from DPDK being static and not directly available from the library. My FFI interface is here:
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;
}
I've also got a library referencing this and wrapping the functions:
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
}
And a build.rs file for linking the libraries -
//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");
}
When I attempt to compile my own application against the FFI interface, I keep getting errors about undefined references to rte_lcore_id
and rte_get_next_lcore
. According to the DPDK's API documentation, those functions are part of the librte_eal library, but are defined in rte_lcore.h as static functions. I'm assuming that these being static functions I will not be able to see them from Rust.
In the helloworld example app that is bundled with DPDK they are importing rte_lcore.h directly. I take it this is why they can access these functions without just referencing librte_eal?
Is there a method to access this in Rust or would there have to be something like a shim in C that let me wrap those functions and make them available via FFI?
static
function is that they are not supposed to be used outside the current compilation unit and therefore even if not inlined their symbols can be private (and inaccessible outside the library). – Matthieu M.