Errors when using FFI

Hi

I was trying out FFI and was trying to call printf. The code compiled without errors but trying to run it in Mac showed Segmentation Fault: 11, which is probably some memory error.

#[link(name = "c++")]
extern
{
	fn printf(stringprint: std::ffi::CString, ...) -> std::os::raw::c_int;
}

fn call_cpp_printf()
{
	let mut printstring = std::ffi::CString::new("%s").unwrap();
	let mut printstring2 = std::ffi::CString::new("printing using printf\n").unwrap();

	unsafe
	{
		printf(printstring,printstring2);
	}
}

I stepped through the program using lldb and the backtrace was showing an error occurred in platform_strlen. It tried to access a memory location in the register RDI but it was 0x0.

error: need to add support for DW_TAG_base_type '()' encoded with DW_ATE = 0x7, bit_size = 0
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x00007fff68c00e52 libsystem_platform.dylib` _platform_strlen  + 18
    frame #1: 0x00007fff68a9c891 libsystem_c.dylib` __vfprintf  + 5379
    frame #2: 0x00007fff68ac2ad3 libsystem_c.dylib` __v2printf  + 475
    frame #3: 0x00007fff68a9b2b2 libsystem_c.dylib` vfprintf_l  + 54
    frame #4: 0x00007fff68a9941e libsystem_c.dylib` printf  + 174
    frame #5: 0x0000000100001c29 rust_ffi` rust_ffi::call_cpp_printf::hf70cc4fcd5699d64  + 217 at main.rs:47
    frame #6: 0x0000000100001c69 rust_ffi` rust_ffi::main::ha94cc790d32bba4b  + 9 at main.rs:71

It was stuck at this instruction and the register RDI was 0x0.

0x7fff68c00e52 <+18>: pcmpeqb xmm0, xmmword ptr [rdi]

As the Rust code managed to compile, I am not sure which part of the Rust code was wrong.

CString is not char* in C. It's like String but for nul-terminated byte sequence, a struct with the size of 3 ptrs. Check the example section of the document to see how should it be used.

https://doc.rust-lang.org/stable/std/ffi/struct.CString.html

(fun point is that if you read the doc carefully you can find the mention that you should read the doc carefully before use :stuck_out_tongue:)

So the reason of the segfault is that the extern block contains invalid function signature.

2 Likes

link(name = "c++") isn't doing what you think it does, either.

Thanks @Hyeonu and @H2CO3

Managed to get it working with the following changes.

extern
{
	fn printf(stringprint: *const c_char, ...) -> std::os::raw::c_int;
}

fn call_cpp_printf()
{
	let mut printstring = std::ffi::CString::new("%s").unwrap();
	let mut printstring2 = std::ffi::CString::new("printing using printf\n").unwrap();

	unsafe
	{
		printf(printstring.as_ptr(),printstring2.as_ptr());
	}
}