Я понимаю вашу точку зрения, что пройти через это беспорядок.
Позвольте мне предположить, что у вас есть не просто новый метод, у вас также есть явный метод удаления. В этом случае вы можете выделить shared_ptr.
extern "C" K k_new_foo() {
// not using auto for the sake of clarity in the example
std::shared_ptr<library::Foo> ptr = library::Foo::Create();
// return the raw pointer as a long long int in a kdb object
return kj(reinterpret_cast<long long>(new std::shared_ptr<library::Foo>(ptr)));
}
extern "C" void k_delete_foo(K k) {
delete reinterpret_cast<std::shared_ptr<library::Foo> *>(k.foo));
}
extern "C" void k_thread_foo(K k) {
auto &ptr = *reinterpret_cast<std::shared_ptr<library::Foo> *>(k.foo));
std::thread{[ptr]{ /* Do something */ }}.detach();
}
Конечно, это не очень хороший способ кодирования. Тем не менее, он позволяет вам сохранить shared_ptr
для всего вашего кода C ++, при этом возможны утечки памяти / ub при неправильном использовании из другого языка.
Если вы хотите защитить от неправильного использования. Вместо этого вы можете собрать все указатели в какой-то глобальной переменной. Таким образом, вы можете сначала проверить, является ли этот указатель общим для другого языка. Вместо передачи нового shared_ptr, вы можете поделиться с ним необработанным указателем, и поведение может стать более определенным, так как при выходе будут вызваны все деструкторы. Недостаток включает в себя больше бухгалтерии, что будет заметно как снижение производительности.
Если вы просто хотите прикрепить владение к необработанному указателю, который вы передаете, без такого метода удаления, я могу порекомендовать вам какую-то утечку памяти, собирая все в глобальный вектор.