Managing best practices for packaging a shared library

The library ooqpwas put in place at my workplace. At the moment, the student is completing it, and I wonder how best to deal with it. The following is an example of the function used by the program:

newQpGenSparse( double ** c, int nx,
    int ** irowQ, int nnzQ, int ** jcolQ, double ** dQ,
    double ** xlow, char ** ixlow,
    double ** xupp, char ** ixupp,
    int ** irowA, int nnzA, int ** jcolA, double ** dA,
    double ** b, int my,
    int ** irowC, int nnzC, int ** jcolC, double ** dC,
    double ** clow, int mz, char ** iclow,
    double ** cupp, char ** icupp,
    int * ierr );

http://pages.cs.wisc.edu/~swright/ooqp/ooqp-userguide.pdf

Correctly? The library is written in c++, so I'm looking for a way to rationally manage memory.

The use of conjugated links is necessary when interacting with these functions, but I was hoping that perhaps the best way to do this is to use std::shared_ptrand then expose the raw memory for these functions. This has an obvious drawback that usage shared_ptrwill be impaired, especially if the memory is deleted or edited by functions ooqp.

Is there a better way to handle this other and then just be careful with the new one and delete it?

+4
source share
2 answers

! , . , , (, !).

class QPGenSparseWrapper
{
    // Only store params if you want to manage their memory.
    double* Param1;

public:
    QPGenSparseWrapper(const double* param1, const int param2 /* , ... */, param16 = 22) :
        Param1(param1),
    {
        newQpGenSparse(&Param1, param2 /* , ... */, param16);
    }

    virtual ~QPGenSparseWrapper()
    {
        freeQpGenSparse(/* params */);

        // If no corresponding free, use smart pointers or manual delete.
    }

    void Run(/* more params?!? */)
    {
        // I hope you know what goes here.
    }
};

, , .

+2

, . , , , .
std::shared_ptr freeQpGenSparse.

template<class T>
struct arg_type_to_wrapper_arg_type { typedef T result; };
template<class T>
struct arg_type_to_wrapper_arg_type<T*> { typedef T& result; };
template<class T>
struct arg_type_to_wrapper_arg_type<T**> { typedef std::shared_ptr<T>& result; }; // or unique_ptr

template<class T>
struct arg_value_setter_base {
    arg_type_to_wrapper_arg_type<T>& m_value;
    T m_new_value;
    T& get() { return m_new_value; }
};

template<class T>
struct arg_value_setter : public arg_value_setter_base<T> {
    arg_value_setter(arg_type_to_wrapper_arg_type<T>& value) : m_value(value), m_new_value(value) {}
    ~arg_value_setter() { }
};
template<class T>
struct arg_value_setter<T*> : public arg_value_setter_base<T*> {
    arg_value_setter(arg_type_to_wrapper_arg_type<T>& value) : m_value(value), m_new_value(null_ptr) {}
    ~arg_value_setter() { m_value = *m_new_value; }
};
template<class T>
struct arg_value_setter<T**> : public arg_value_setter_base<T**> {
    arg_value_setter(arg_type_to_wrapper_arg_type<T>& value) : m_value(value), m_new_value(null_ptr) {}
    ~arg_value_setter() { m_value.reset(*m_new_value); }
};

#define CREATE_WRAPPER_FOR_OOQP_ALLOC_FUNCTION(ret_type, function_name, arg_sequence) \
/* use boost preprocessor macros to get the following result. You just have to use BOOST_PP_SEQ_FOR_EACH_I 3 times. I will leave this job for you. */

void newQpGenSparseWrapper(
    arg_type_to_wrapper_arg_type<double **>::result arg_0, // std::shared_ptr<double>& arg_0
    arg_type_to_wrapper_arg_type<int>::result arg_1, 
    arg_type_to_wrapper_arg_type<int **>::result arg_2, // std::shared_ptr<int>& arg_2
    .....,
    arg_type_to_wrapper_arg_type<int *>::result arg_x // int& arg_x
    )
{
    arg_value_setter<double **> arg_setter_0(arg_0); 
    arg_value_setter<int> arg_setter_1(arg_1); 
    arg_value_setter<int **> arg_setter_2(arg_2); 
    .....,
    arg_value_setter<int *> arg_setter_x(arg_x);
    // TODO: you may want to avoid the assignment in case of the failure of the function to prevent shared_ptr from getting an invalid pointer 
    return newQpGenSparse(arg_setter_0.get(), arg_setter_1.get(), arg_setter_2.get(), .... , arg_setter_x.get());
}

, :

CREATE_WRAPPER_FOR_OOQP_ALLOC_FUNCTION(void, newQpGenSparse, (double **)(int)(int **) .... (int *) );
0

All Articles