我有一个板条箱,其中存放一个函数指针(用C定义),并调用一些预定义的参数。我怀疑我无法获得符合C调用约定的调用。我已经审查了the relevant Rust docs,并认为我在适当的地方指定了调用约定...
一个简单的例子来说明:
带有简单结构的Rust板条箱,其中包含缓冲区和用于包装它的函数指针:
pub type Callback = extern "C" fn(buffer: &mut [u8], current_index: u32, max_index: u32) -> u32;
const BUFFER_SIZE: usize = 32_767;
pub type DataBuffer = [u8; BUFFER_SIZE];
#[no_mangle]
pub struct Foo {
buffer: DataBuffer,
pub current_index: u32,
callback: Option<Callback>,
}
impl Foo {
fn new() -> Self {
Foo {
current_index: 0,
buffer: [0u8; BUFFER_SIZE],
callback: None,
}
}
fn add_callback(&mut self, callback: Callback) {
self.callback = Some(callback);
}
fn call_callback(&mut self) {
let increment = self.callback.expect("")(
self.buffer
.get_mut(self.current_index as usize..)
.expect(""),
self.current_index,
BUFFER_SIZE as u32,
);
self.current_index += increment;
}
}
#[no_mangle]
pub extern "C" fn FooNew() -> Box<Foo> {
Box::new(Foo::new())
}
#[no_mangle]
pub extern "C" fn FooAddCallback(foo: &mut Foo, callback: Callback) {
foo.add_callback(callback);
}
#[no_mangle]
pub extern "C" fn FooCallCallback(foo: &mut Foo) {
foo.call_callback();
}
#[no_mangle]
pub extern "C" fn FooPrint(foo: &mut Foo) {
for c in foo.buffer.iter() {
print!("{}", *c as char);
}
println!("\n");
}
和一些相应的C代码来调用它:
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Foo Foo;
extern Foo* FooNew();
extern void FooAddCallback(Foo* foo, void* callback);
extern void FooCallCallback(Foo* foo);
extern void FooPrint(Foo* foo);
unsigned int getHeaders(char* buffer, unsigned int current_index, unsigned int max_index)
{
if (current_index > max_index)
{
printf("\nError current_index(%d) > max_index(%d) !!\nThis is most likely a C-api byte order problem\n", current_index, max_index);
exit(-1);
}
strcpy(buffer, "~HEADER~\0");
return 9;
}
int main()
{
Foo* foo = FooNew();
FooAddCallback(foo, getHeaders);
FooCallCallback(foo);
FooCallCallback(foo);
FooCallCallback(foo);
FooPrint(foo);
return 0;
}
运行时,回调的后两个参数传递不正确(即current_index
的参数传递给max_index
,反之亦然,在上面的示例中,其0传递给{{1 }}和32767到max_index
)。反转这些args的顺序(看似使调用顺序读取不正确)会导致其正确执行...
我怀疑我只是在错误地调用回调,或者需要以其他方式指定调用约定。
是的,提到了this question。这是他们问题的直接反面,但是精神是相同的。 阵列/切片无法直接通过FFI 传递。