Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ wrap C struct *and* and functions

Tags:

c++

c

struct

I'm trying to wrap a C library which uses patterns like this:

Thing* x= new_thing_("blah");
Thing* tmp= thing_copy(x);
free_thing(tmp);
Other* y=get_other(x,7);
char* message=get_message(x,y);
free_thing(x);
free_other(y);

In c++, I'd like to be able to do something like

auto_ptr<CXXThing> x=new CXXThing("blah");
auto_ptr<CXXThing> tmp=new CXXThing(*x);
auto_ptr<CXXOther> y=x->get_other(7);
char* message = y->get_message();

Obviously, CXXOther wraps a pointer to a CXXThing as well. So the problem I'm encountering is that essentially I'd like to just "insert" functions and members into existing structs (I think this is known as the "Mixin" idea).

The problem is that if I include a Thing as an element of the CXXThing, then I don't know how I'd declare the constructor, and if I include a pointer to the wrapped class, then I have an extra level of useless indirection.

How should I wrap it so that this is possible? (An answer of "What you want to do is not best/possible... here is the proper way" is also acceptable.)

like image 423
Jeremy Salwen Avatar asked Apr 27 '26 11:04

Jeremy Salwen


1 Answers

Instead of using auto_ptrs, you can use the RAII idiom more directly. Here's one way you can do it:

A CXXThing class that wraps a Thing:

class CXXThing
{
public:
    // Acquire a Thing
    explicit CXXThing(const char* str) : x(::new_thing_(str)) {}
    // Copy a Thing
    CXXThing(const CXXThing& rhs) : x(::thing_copy(rhs.x)) {}
    // Copy-and-swap idiom
    CXXThing& operator=(CXXThing rhs)
    {
        swap(*this, rhs);
        return *this;
    }
    // Release a Thing
    ~CXXThing() { ::free_thing(x); }

    friend void swap(CXXThing& lhs, CXXThing& rhs)
    {
        Thing* tmp = lhs.x;
        lhs.x = rhs.x;
        rhs.x = tmp;
    }

private:
    Thing* x;
    friend class CXXOther;
};

A CXXOther class that wraps an Other:

class CXXOther
{
public:
    // Acquire an Other
    explicit CXXOther(CXXThing& thing, int i) : y(::get_other(thing.x, i)) {}
    // Release an Other
    ~CXXOther() { ::free_other(y); }
    // Get a message
    char* get_message(const CXXThing& x) { return ::get_message(x.x, y); }
private:
    // Instaces of Other are not copyable.
    CXXOther(const CXXOther& rhs);
    CXXOther& operator=(const CXXOther& rhs);
    Other* y; 
};

Translating your C code into C++ code with the above classes:

int main()
{
    CXXThing x("blah");

    {
        CXXThing tmp = x;
    } // tmp will go away here.

    CXXOther y(x, 7);
    char* msg = y.get_message(x);
    return 0;
}
like image 173
In silico Avatar answered Apr 28 '26 23:04

In silico



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!