Del*_*ore 3 windows 32-bit ffi rust
我的Rust测试代码
extern "C" {
fn test_int_only(n : libc::c_int);
fn test_int_and_str(s : CString , n : libc::c_int);
}
pub fn test1() {
unsafe {
test_int_only(0);
test_int_only(1);
test_int_only(2);
test_int_only(4);
test_int_only(-12);
}
}
pub fn test2() {
unsafe {
test_int_and_str(CString::new("Foo").unwrap(),0);
test_int_and_str(CString::new("Bar").unwrap(),1);
test_int_and_str(CString::new("Baz").unwrap(),2);
test_int_and_str(CString::new("Fub").unwrap(),4);
test_int_and_str(CString::new("Bub").unwrap(),-12);
}
}
Run Code Online (Sandbox Code Playgroud)
我的C代码
void test_int_only(int abc){
printf("%d\n", abc);
}
void test_int_and_str(const char* name,int abc) {
printf("%s %d\n", name, abc);
}
Run Code Online (Sandbox Code Playgroud)
测试test_int_only()时
1
2
4
-12
Run Code Online (Sandbox Code Playgroud)
测试test_int_and_str()时
Foo 4
Bar 4
Baz 4
Fub 4
Bub 4
Run Code Online (Sandbox Code Playgroud)
似乎第二个arg被解释为(在rust或c中)作为sizeof字符串,而不是从Rust代码传递的值.我猜它与调用约定或空终止无法正常工作有关.它是一个C dll,带有_cdecl(windows 32bit dll)调用约定.有趣的是,传递(不透明)指针和int(在另一个测试中)工作正常,所以我不认为这是一个调用约定问题.
似乎第二个arg被解释为(在rust或c中)作为sizeof字符串,而不是从Rust代码传递的值.
正确.您在这里遇到了未定义的行为.
您的C函数与您在Rust-Code中声明的extern函数具有不同的签名.首先,传递不#[repr(C)]属于extern函数的类型是未定义的行为,并且曾经有过这种afai的lint.其次,a CString不是a char*,它是带有内部数据的结构.如果你想通过const char*,你必须通过*const u8.你可以CString通过into_ptr函数获得这样的指针.
注意into_ptr泄漏内存,需要from_ptr再次使用才能获得CString可以解除分配的对象.如果您只想借出CString对象,可以按照以下方式执行操作:
// ensure c_str lives longer than the function call
let c_str = CString::new("Foo").unwrap();
unsafe { test_int_and_str(c_str.as_ptr(), 0); }
// let the destructor of c_str free the memory
Run Code Online (Sandbox Code Playgroud)