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

Wade Ward

Grey Alien said:
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 ...
How does it compile and link?
 
G

Grey Alien

Wade said:
How does it compile and link?

It compiles/links fine ... but I suspect that it is at run time that
I'll find signs that say "here be monsters" ... Since any problems are
likely to be caused by one (or more of the ff):

1). "dangling" pointers
2). Attempt to dealloc memory more than once
3). Attempt to free memory alloc'd with 'new' (or vice-versa)
4). memory leaks

I can't find that out yet for sure, because I'm still developing the
application.
 
C

CBFalconer

Grey said:
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:

Here you are using C++ code, illegal in C. Thus off-topic here.
 
D

Default User

Grey said:
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.


That would make it a proper topic for comp.lang.c++.





Brian
 
R

Richard Tobin

#ifdef __cplusplus
extern "C"
....

Here you are using C++ code, illegal in C. Thus off-topic here.[/QUOTE]

Since __cplusplus is not defined when using standard C, it's perfectly
legal C.

-- Richard
 
K

Kevin Bagust

[/QUOTE]

Restored sniped context
Since __cplusplus is not defined when using standard C, it's perfectly
legal C.

But the

struct MyStruct
{
public:

is illegal and not protected by an #ifdef.

Kevin.
 
J

Jorgen Grahn

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.

I think it makes more sense to leave the C library alone (presumably
it works well as a C library) and create a separate C++ wrapper.
C++ is good at that kind of thing; it can be done with minimal
run-time performance penalty.

Mixing the two interfaces together just makes them harder to
understand, IMHO.

/Jorgen
 

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

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,733
Latest member
LonaMonzon

Latest Threads

Top