Help with ffi bindings

So this is what my C function looks like (in C):

int return_netaddr_crypt_check(char *ipaddr) {/* ... */}

This is what is it looks like after using the rust-bindgen:

extern "C" {
    pub fn return_netaddr_crypt_check(ipaddr: *mut ::std::os::raw::c_char) -> ::std::os::raw::c_int;
}

Now how do I call this function from Rust to pass a String such as "10.23.2.3"?
How would I go about it? Can anyone provide some example code?

Have a look at the documentation for std::ffi::CString`. The top level example is almost identical to what you're looking for:

use std::ffi::CString;
use std::os::raw::c_char;

extern {
    fn my_printer(s: *const c_char);
}

// We are certain that our string doesn't have 0 bytes in the middle,
// so we can .expect()
let c_to_print = CString::new("Hello, world!").expect("CString::new failed");
unsafe {
    my_printer(c_to_print.as_ptr());
}

This is what I did:

mod netio_hpc_lib; // This contains all the bindings
fn main() {
    let slice: &str = "41.23.88.96";
    let c_msg = std::ffi::CString::new(slice).unwrap();
    let x = unsafe {netio_hpc_lib::return_netaddr_crypt_check(c_msg.as_ptr())};
    println!("Address: {}", x);
}

Now I get this error:

undefined reference to `return_netaddr_crypt_check' collect2: error: ld returned 1 exit status

Looks like a linker error. Basically, you've done everything necessary to call that function, but when rustc tries to generate an executable it can't find anything when trying to resolve the return_netaddr_crypt_check symbol.

If netio_hpc_lib is a 3rd party crate, they should have a build.rs script which tells rustc which native libraries to inspect when looking for symbols, and you should create an issue against their repository.

If these are your declarations (e.g. you generated them with bindgen) you'll need to write your own build.rs file. At the bare minimum, build.rs should tell rustc which library to link to by printing something like cargo:rustc-link-lib=some_library (if you're trying to link to libsome_library.a) and let rustc know possible directories to check when looking for libsome_library.a by printing something like cargo:rustc-link-search=native=/path/to/libs (if libsome_library.a was located in /path/to/libs).

1 Like

If you're wanting a more in-depth explanation, @kornel has written an excellent article on the topic. I would recommend checking it out if you want a better understanding on how you can link to a native library and the various conventions the Rust ecosystem has established around this.