Mixing C++ and C


G

Grey Alien

I have an existing ANSI C library which makes extensive use of structs.
I use these structs in my C++ code, but would like to benefit from C++
features such as ctors/dtors etc. I have modified the C header, as shown
below, with inline functions, so that I can benefit from C++ features,
whilst keeping the rest of the C library intact.

One thing I had to be particularly careful of is the fact that in a lot
of the C API functions, struct assignments were made (i.e. shallow
copies). I have therefore implemented the (overloaded) assignment
operator to create 'shallow' copy by default (so this is consistent with
the C API so that a pointer to the struct could be passed to a C API
function with no adverse effect). The facility still exists for an
(explicit) deepcopy. This is is what I have come up with so far. The CPP
snippet at the end of the post shows how I intend to use it.


//Header File

#ifdef __cplusplus
extern "C"
{
#endif

struct MyStruct
{
public:
MyStruct(const size_t size)
:m_shallow_copied(false)
{
if (!fooAlloc(this, size))
throw new std::bad_alloc ;
}

MyStruct(const MyStruct& ms)
:m_shallow_copied(false)
{
//deep copy because only C++ API calls this ctor
copy(ms, true);
}

MyStruct& operator= (const MyStruct& rhs)
{
//Default shallow copy on assignments
if (this != &rhs)
copy(rhs);
return *this ;
}

//explicit deepcopy
void deepcopy(const struct MyStruct* rhs)
{
copy(rhs,true);
}

~MyStruct::MyStruct
{
if (!m_shallow_copied && m_ptr)
fooFree(this);
}

//Needs to be public - for C API (too many funcs to all be friends)
void * m_ptr ;
size_t m_size ;

private:
void copy(const MyStruct& rhs, const bool deepcopy=false)
{
if (deepcopy)
{
//do we own ptr? (if so, free first)
if (m_ptr && !m_shallow_copied)
fooFree(this);

if (fooAlloc(this, rhs.size ))
throw new std::bad_alloc ;

fooCopy(this, &rhs) ;
m_shallow_copied = false ;
}
else
{
//default
m_ptr = rhs.m_ptr ;
m_size = rhs.m_size ;
m_shallow_copied = true ;
}
}

bool m_shallow_copied ;
};


/* Pure C API */
long fooAlloc(struct MyStruct* ms, const unsigned int size);
void fooFree(struct MyStruct* ms);
void fooCopy(struct MyStruct* dest, const struct MyStruct* src);
long fooJustDoIt(const struct MyStruct* ms);

#ifdef __cplusplus
};
#endif



//Sample cpp file using MyStruct (should probably use auto_ptr instead
of raw pointers ...)

#include "MyStruct.h"

class MyClass
{
public:
MyClass(const size_t s)
{ ms = new MyStruct(s); }

MyClass(const MyClass&);

~MyClass()
{delete ms ;}

long DoSomething() const
{
//pass ptr to MyStruct to C function
return fooJustDoIt(ms);
}

private:
MyStruct * ms ;
};


I would appreciate some feedback as to whether there are any subtle (or
not so subtle) caveats/gotchas I must be aware of with this approach ...
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top