C wrap creates and destroys functions using smart pointer

I have a C API that handles the creation and destruction of an object, it provides: createObject(...)and destroy(...). I want to combine it into several more modern build / destroy mechanisms and use them with smart pointers. I am afraid that at some point I will forget to destroy the object, or some kind of exception will occur.

I know the custom function of the deleter for shared_ptr, but I cannot explicitly call newbecause the function createOjbectis initializing.

Can STL smart pointers be used in this situation? Should I implement a class from scratch with initialization in the constructor, destruction in the destructor and reference counting in this situation?

+4
source share
3 answers

std::shared_ptrfully capable of creating and deleting an object with cutstom creator and deleting, but instead newyou should use the creator function.

Consider the following creator and deletion:

typedef struct {
    int m_int;
    double m_double;
} Foo;

Foo* createObject(int i_val, double d_val) {
    Foo* output = (Foo*)malloc(sizeof(Foo));

    output->m_int = i_val;
    output->m_double = d_val;

    puts("Foo created.");
    return output;
}

void destroy(Foo* obj) {
    free(obj);
    puts("Foo destroyed.");        
}

To control the instance Foocreated by the above functions, simply follow these steps:

std::shared_ptr<Foo> foo(createObject(32, 3.14), destroy);

Use std::shared_ptris overhead if you do not want to share the property of the property. In this case, it’s std::unique_ptrmuch better, but for this type you have to define a custom delete functor with which it can remove the managed Fooinstance:

struct FooDeleter {
    void operator()(Foo* p) const {
        destroy(p);
    }
};
using FooWrapper = std::unique_ptr<Foo, FooDeleter>;

/* ... */

FooWrapper foo(createObject(32, 3.14));
+6

++ 17.

template<auto X> using constant_t=std::integral_constant<std::decay_t<decltype(X)>, X>
template<auto X> constexpr constant_t<X> constant{};
template<class T, auto dtor> using smart_unique_ptr=std::unique_ptr< T, constant_t<dtor> >;

, API- API Bob Bob* createBob(some_args...) destroyBob(Bob*):

using unique_bob=smart_unique_ptr< Bob, destroyBob >;
unique_bob make_unique_bob(some_args args){
  return unique_bob( createBob(args) );
}

a unique_bob shared_ptr<Bob>.

++ 14:

template<class T, void(*dtor)(T*)> using smart_unique_ptr=std::unique_ptr< T, std::integral_constant<decltype(dtor),dtor> >;

dtor- void(T*).

++ 11 .

+1

Submitting a complete solution for my case:

Based on @Akira's suggestions, I wrapped it with a shared pointer, because I want this object to be shared in many palaces, and lambda:

// coming from some API:
struct SomeStruct;
bool initializedata(SomeStruct **data);
bool destorycdata(SomeStruct **data);

class SomeStructWrapper
{
public:
    SomeStructWrapper()
    {
        SomeStruct* data;
        if(initializedata(&data))
        {
            m_data = std::shared_ptr<SomeStruct>(data, [](SomeStruct* ptr){
                destorycdata(&ptr);
            });
        }
        else
        {
            throw std::runtime_error("Data was not initalized");
        }
    }

    const SomeStruct* operator->() const {return m_data.get();}
    SomeStruct* operator->() {return m_data.get();}

private:
    std::shared_ptr<SomeStruct> m_data;
};
0
source

Source: https://habr.com/ru/post/1684511/


All Articles