Функция Rust, которая выделяет память и вызывает C ++ callback, вылетает - PullRequest
0 голосов
/ 05 мая 2018

Код ржавчины:

#[repr(C)]
pub struct Tmp {
    pub callback: extern "C" fn(i: i32),
}

#[no_mangle]
pub extern "C" fn set_callback(callback: extern "C" fn(i: i32)) -> *mut Tmp {
    let mut tmp = Box::new(Tmp { callback });
    println!("tmp as ptr: {:p}", tmp); // >> here <<
    &mut *tmp
}

#[no_mangle]
pub extern "C" fn use_callback(tmp_ptr: *mut Tmp) {
    unsafe {
        ((*tmp_ptr).callback)(1);
        ((*tmp_ptr).callback)(3);
    }
}

C ++ код:

struct Tmp {
    void (*callback)(int32_t);
};

typedef Tmp*(__stdcall* set_callback_t)(void(*callback_t)(int32_t));
typedef void(__stdcall* use_callback_t)(Tmp*);

void callback(int32_t i) {
    printf("%d\n", i * 2);
}

int main() {
    // ... loading rust part as .dll
    // ... checking if loaded correctly
    Tmp* tmp_ptr = set_callback(callback);
    printf("tmp_ptr %p\n", tmp_ptr);
    use_callback(tmp_ptr);
    // ... freeing the .dll
}

Когда я компилирую эту программу, она работает как положено. Напечатанные значения указателя на структуру Tmp в Rust и C ++ совпадают. Когда я комментирую println в Rust, происходит сбой программы на C ++, что означает, что с этим (возможно, частью Rust) что-то не так.

Я использую код Rust в качестве .dll. Я хотел бы передать указатель на функцию C ++ в функцию set_callback, а затем я бы хотел использовать этот указатель в функции use_callback при вызове use_callback в коде C ++.

Насколько я понимаю, в конце мне придется вызвать функцию Rust, чтобы отбросить структуру Tmp, но я пропустил это.

1 Ответ

0 голосов
/ 05 мая 2018

Box в Rust похож на std::unique_ptr в C ++. При создании tmp указанные данные будут освобождены в конце функции.

Чтобы «просочить» указатель в мир C ++, вы должны использовать Box::into_raw.

Обратите внимание, что поскольку нет гарантии, что Rust и C ++ выделяют память одинаково; вам придется передать указатель обратно в Rust и использовать Box::from_raw для его освобождения.

...