Mixing C and C++



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 ...


.



Relevant Pages

  • passing a struct from managed code to unmanaged function
    ... I would like to know how do I pass a pointer to a struct from managed ... void*. ... How do I pass the structure MYSTRUCT to the Addobjectfunction. ...
    (microsoft.public.dotnet.languages.csharp)
  • passing a struct to unmanaged function
    ... I would like to know how do I pass a pointer to a struct from managed ... void*. ... How do I pass the structure MYSTRUCT to the Addobjectfunction. ...
    (microsoft.public.dotnet.framework.interop)
  • Re: why still use C?
    ... >void foo(struct MyStruct struct){} ... but in C you have to explicitly create a typename ...
    (comp.lang.c)
  • Re: Question about setjmp on Itanium HPUX.
    ... that was the sound of the alignment of your struct ... jmp_buf and your struct. ... The one value which you are guaranteed is safe for struct mystruct is ... Note that in this case, as in your original code, you need to remember ...
    (comp.lang.c)
  • Re: typedefing a struct
    ... typedef struct mystruct { ... typedef struct mystruct mystruct; ...
    (comp.lang.c)