Я не могу просто взять необработанный указатель, потому что тогда код C ++ не знает, что у меня есть ссылка на Foo
, и может вызвать его деконструктор.
Да и нет. С вашим реальным примером. C ++ передаст право владения shared_ptr
тому, кто вызвал create_foo
, поэтому C ++ знает, что есть еще что-то, что владеет указателем.
Вам необходимо добавить функцию get
, которая будет получать значение для вас, не теряя владения указателем, что-то вроде этого:
extern "C" {
std::shared_ptr<Foo> create_foo() {
// do the thing
}
/* or maybe this
std::shared_ptr<Foo> &&create_foo() {
// do the thing
}
*/
Foo *get_foo(std::shared_ptr<Foo> &foo) {
foo.get();
}
void destroy_foo(std::shared_ptr<Foo> foo) {
}
/* or maybe this
void destroy_foo(std::shared_ptr<Foo> &&foo) {
}
*/
}
Также shared_ptr<Foo>
не является допустимым C, поэтому я не знаю, принимают ли bindgen и C ++ это (возможно, предупреждение), но это уже присутствует в вашем коде.
На стороне Rust вы можете сделать это:
// must be generated by bindgen and this might create a lot of problems
// this need to be the same struct as the shared_ptr on the C++ side.
// if even one octet is not correct you will run into bugs
// BE SURE that bindgen don't implement Copy for this
struct shared_ptr<T>;
struct Foo(i32);
extern "C" {
fn create_foo() -> shared_ptr<Foo>;
fn get_foo(foo: &shared_ptr<Foo>) -> *mut Foo;
fn destroy_foo(foo: shared_ptr<Foo>);
}
fn main() {
unsafe {
let my_shared_foo = create_foo();
let foo = get_foo(&my_shared_foo);
(*foo).0;
destroy_foo(my_shared_foo);
}
}
Конечно, это всего лишь пример, и в этом нет ничего действительно безопасного. И поскольку я не могу проверить, пожалуйста, дайте мне знать, если я написал что-то, что не работает. bindgen
должен сделать работу.