7

I am developing an application in C, where I need to used a 3rd party C++ library. So, I am basically writing a wrapper around the C++ library to make it possible to call it from my application which is in pure C. Some of the methods in the library returns pointer of type boost::shared_ptr, which I need to cast to void* [for C] and then convert it back to boost::shared_ptr type to reuse it for further processing. I used the following ways to do the conversion:

To void* :

void * func1()
{
    //after the boost::shared_ptr is created
    return static_cast<void *> (SHARED_PTR.get())
}

From void* :

void func2(void * VOID_PTR) //VOID_PTR returned by func1
{
    boost::shared_ptr<T> SHARED_PTR = *(boost::shared_ptr <T> *)(VOID_PTR);
}

However, I am getting SIGSEGV in func2, which I believe is happening because the shared_ptr being deallocated because its ref-count getting 0.

I was looking for correct ways to do this conversion and suggestions from experts of the SO community.

Thanks in advance!

Saurav Haloi
  • 343
  • 1
  • 2
  • 11
  • 1
    Shouldn't the back-cast really be an initialization instead? Such as `boost::shared_ptr(VOID_PTR)`? –  Dec 14 '13 at 11:36
  • No. Then you'd have two smart pointers both with responsibility to delete that pointer. – Cheers and hth. - Alf Sep 28 '18 at 15:26
  • @Cheersandhth.-Alf "_Then you'd have two smart pointers_" I don't think you'd have anything: if you can't do `delete p;` how could you do `boost::shared_ptr(p)`? – curiousguy Nov 07 '18 at 23:58

3 Answers3

8

Think about who owns the instance of T, and when.

I'm guessing you're getting a shared_ptr from your C++ library function, getting its value, then letting the shared_ptr go out of scope. When this happens, as you suggested, the managed object will be deleted.

To get around this, you will have to keep the original shared_ptr alive for the lifetime of your use of its managed object.

void* func1(const boost::shared_ptr<T>& sharedPtr)
{
    add_to_some_kind_of_persistent_storage(sharedPtr);
    return static_cast<void*>(sharedPtr.get());
}

You could also use a trick with a customer deleter object to effectively release the managed object from the shared_ptr, but this might not be safe if there are other instances of shared_ptr hanging around which manage the same object. See here: Detach a pointer from a shared_ptr?

To pass it back in:

boost::shared_ptr<T> func2(void* voidPtr) //VOID_PTR returned by func1
{
    return boost::shared_ptr<T>(voidPtr);
}
Community
  • 1
  • 1
2

nowadays that shared_ptr is part of the standard library

std::shared_ptr<type> ptr;
auto ptr1 = reinterpret_cast<void *>(&ptr); /* shared_ptr > void ptr */
auto ptr2 = * reinterpret_cast(std::shared_ptr<type>*)(ptr1); /* void ptr > shared_ptr */
Jonathan
  • 595
  • 5
  • 10
1

What to do depends on what the C library does with the void* pointer. If it at some point is used as a T* then that's what you need to pass, as you're doing. To get back a shared_ptr you then need T to implement boost::enable_shared_from_this, and call its shared_from_this member function, i.e. reinterpret_cast<T*>(void_ptr)->shared_from_this().

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331