Вызов функции Rust с параметром функции из C приводит к ошибке SegFault - PullRequest
1 голос
/ 19 июня 2020

Я создаю общий объект в Rust и связываю его в C. Компиляция / компоновка работает нормально, но как только я вызываю функцию, я получаю SegFault.

Объявление функции Rust: она использует два целых числа / usize и ссылку на функцию, которая возвращает целое число / usize.

#[no_mangle]
pub fn show_loading_animation(from: usize,
                              to: usize,
                              progress_in_percentage_fn: &dyn Fn() -> usize) { ... }

Я вызываю его из C вот так:

typedef long long usize; // 64 bit
extern void show_loading_animation(usize, usize, usize (*prog_fn)());

usize progress_reporter() {
    return 80l;
}

int main(void) {
    show_loading_animation(0, 100, &progress_reporter);
    return 0;
}

Я предполагаю, что &dyn Fn() несовместим со ссылкой на функцию c? Я отлаживал show_loading_animation с помощью gdb. Это сборка, и последняя строка - это место, где она вылетает.

0000000000004530 <show_loading_animation>:
4530:       55                      push   %rbp
4531:       41 57                   push   %r15
4533:       41 56                   push   %r14
4535:       41 55                   push   %r13
4537:       41 54                   push   %r12
4539:       53                      push   %rbx
453a:       48 81 ec f8 00 00 00    sub    $0xf8,%rsp
4541:       48 89 94 24 e0 00 00    mov    %rdx,0xe0(%rsp)
4548:       00 
4549:       48 89 34 24             mov    %rsi,(%rsp)
454d:       48 39 fe                cmp    %rdi,%rsi
4550:       0f 82 a9 03 00 00       jb     48ff <show_loading_animation+0x3cf>
4556:       48 89 fb                mov    %rdi,%rbx
4559:       48 8b 41 18             mov    0x18(%rcx),%rax
455d:       48 89 84 24 d8 00 00    mov    %rax,0xd8(%rsp)
4564:       00 
4565:       45 31 f6                xor    %r14d,%r14d
4568:       48 8d 6c 24 30          lea    0x30(%rsp),%rbp
456d:       0f 1f 00                nopl   (%rax)
4570:       48 8b bc 24 e0 00 00    mov    0xe0(%rsp),%rdi
4577:       00 
4578:       ff 94 24 d8 00 00 00    callq  *0xd8(%rsp) <-- crash

Ответы [ 2 ]

3 голосов
/ 19 июня 2020

&dyn T - это толстый указатель (в основном указатель на данные и указатель на vtable), C ничего не знает о своей внутренней структуре, поэтому вам нужно вместо этого использовать type Fn = extern "C" fn() -> usize.

0 голосов
/ 19 июня 2020

Я мог бы решить это таким образом. Сейчас я предоставляю две функции: одну для ржавчины, одну для FFI.

// translates extern c function reference to closure function for rust
#[no_mangle]
pub fn show_loading_animation_ffi(from: usize,
                                  to: usize,
                                  progress_in_percentage_fn: extern "C" fn() -> usize) {
    let fn_closure = || {
        progress_in_percentage_fn()
    };
    show_loading_animation(from, to, &fn_closure);
}

Я удалил #[no_mangle] из функции чистой ржавчины (см. Код выше).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...