Wrapping C code into a C++ object

T

Tom the Canuck

What would be the best way to proceed?
Should I make a pure virtual class and then
derive from that? I want the base class to have
functions defined so that I don't have to do the
work all over again in the derived class. Is this
not what objects are for?
Please illuminate on how to do this properly.
I don't want code, just a pointer on how to
do the job right.
Any comments or links will help.

The C code is OpenGL. I just want a class
to make life easier for future projects.
If requested, I can send the source code done
up to now. I do not believe in wasting space, so
it is not in this post.

Thanks in advance,
Tom the Cunuck.
 
R

Roland Pibinger

What would be the best way to proceed?
Should I make a pure virtual class and then
derive from that? I want the base class to have
functions defined so that I don't have to do the
work all over again in the derived class. Is this
not what objects are for?

'Implementation inheritance' isn't necessarily the best way to
proceed. C frameworks are often 'object based' but not polymorphic. So
'delegation' may be better than 'inheritance'.
Please illuminate on how to do this properly.
I don't want code, just a pointer on how to
do the job right.
Any comments or links will help.

The C code is OpenGL. I just want a class
to make life easier for future projects.
If requested, I can send the source code done
up to now. I do not believe in wasting space, so
it is not in this post.

I know nothing about OpenGL but a Google search with 'OpenGL C++'
yields many interesting links. Maybe someone has already done the work
for you.

Best wishes,
Roland Pibinger
 
J

james.moughan

Tom said:
What would be the best way to proceed?
Should I make a pure virtual class and then
derive from that? I want the base class to have
functions defined so that I don't have to do the
work all over again in the derived class. Is this
not what objects are for?

Woah! Why do you reckon you need inheritance here?

Inheriting from a pure virtual class is incredibly
useful if you want multiple objects to share a
common interface and be polymorphic. If you
don't, don't do that.

If you want to share some code between
different classes derived from an interface, then
one option is to put the code in another class
and use multiple inheritance. Derive from
both the interface (pure virtual class) and the
implementation class.

However, if you just want the C code wrapped up
for convenient use -- don't use inheritance, there's
no point. Just make the class.

If you want advice on OO in C++ then a good
place to start is Bjarne Stroustrup's homepage.
He is not shy about expressing his views on the
topic. said:
Please illuminate on how to do this properly.
I don't want code, just a pointer on how to
do the job right.
Any comments or links will help.

The C code is OpenGL. I just want a class
to make life easier for future projects.
If requested, I can send the source code done
up to now. I do not believe in wasting space, so
it is not in this post.

Thanks in advance,
Tom the Cunuck.

HTH

James M
 
J

Jonathan Mcdougall

Tom said:
What would be the best way to proceed?

There is no "best" way in programming.
Should I make a pure virtual class and then
derive from that? I want the base class to have
functions defined so that I don't have to do the
work all over again in the derived class. Is this
not what objects are for?

Well that is a singular way to define what "objects" are for.

http://en.wikipedia.org/wiki/Object_(computer_science)
Please illuminate on how to do this properly.
I don't want code, just a pointer on how to
do the job right.
Any comments or links will help.

The C code is OpenGL. I just want a class
to make life easier for future projects.
If requested, I can send the source code done
up to now. I do not believe in wasting space, so
it is not in this post.

One easy way would be to wrap the C code into a simple class.

class A
{
public:
void f()
{
c_f(&acs); // call the C function from f()
}

private:
a_C_struct acs;
};

If you think the implementation could change (by changing the library
for example), you could hide the implementation (openGL in this case)
using the so called "pimpl" idiom (google for it).


Jonathan
 
T

Tom the Canuck

Tom the Canuck said:
What would be the best way to proceed?
Should I make a pure virtual class and then
derive from that? I want the base class to have
functions defined so that I don't have to do the
work all over again in the derived class. Is this
not what objects are for?
Please illuminate on how to do this properly.
I don't want code, just a pointer on how to
do the job right.
Any comments or links will help.

The C code is OpenGL. I just want a class
to make life easier for future projects.
If requested, I can send the source code done
up to now. I do not believe in wasting space, so
it is not in this post.

Thanks in advance,
Tom the Cunuck.

Thanks for all the replies. My path is now clear and straight ahead.
With a bit of work, I will do what I wanted to do.

Tom the Canuck.
 
B

Bob Hairgrove

What would be the best way to proceed?
Should I make a pure virtual class and then
derive from that? I want the base class to have
functions defined so that I don't have to do the
work all over again in the derived class. Is this
not what objects are for?
Please illuminate on how to do this properly.
I don't want code, just a pointer on how to
do the job right.
Any comments or links will help.

The C code is OpenGL. I just want a class
to make life easier for future projects.
If requested, I can send the source code done
up to now. I do not believe in wasting space, so
it is not in this post.

Thanks in advance,
Tom the Cunuck.

As others have pointed out, there is no "best answer" here. But it
would be interesting to point out in very general terms what
advantages C++ can give you when wrapping a set of C functions which
together constitute some kind of system or library.

Let's start with some of the more important ones:

- RAII ("Resource Acquisition Is Initialization"). Design the C++
class so that it automatically (i.e. upon construction of an object)
allocates all the necessary memory for its members, possibly using
smart pointers for exception safety, and cleans up after itself on
destruction. This might or might not necessarily entail calling memory
allocation and de-allocation functions such as "new" and "delete", but
also other things such as initializing and freeing "handles" or
calling global C initialization and termination functions in the
third-party library. This, IMHO, is one of the areas where C++ really
shines.

- Type safety. Clients need not fool around with passing void pointers
to a function in some circumstances, but casting the same argument to
unsigned int in others and passing an additional "flag" argument so
that the function knows which type to expect (you can tell I'm talking
about ODBC here <g>). Take the all-purpose C library function and
provide several context-specific C++ member functions which pass the
appropriate types.

- Encapsulation. Hide your handles, buffers, etc. from the clients and
use STL containers such as std::string, std::vector, std::list, etc.

- Provide meaningful error parsing, logging and recovery by using C++
exception classes.

Well, I'm just getting started here ... but maybe some other people
would like to continue the list?
 
I

Ian

Bob said:
- Type safety. Clients need not fool around with passing void pointers
to a function in some circumstances, but casting the same argument to
unsigned int in others and passing an additional "flag" argument so
that the function knows which type to expect (you can tell I'm talking
about ODBC here <g>). Take the all-purpose C library function and
provide several context-specific C++ member functions which pass the
appropriate types.
UNIX iotcl are another example of this.
Well, I'm just getting started here ... but maybe some other people
would like to continue the list?
- adding functions or operators to C types, one example that comes to
mind are time type structures where math operators come in very handy.

- portability!

Ian
 
B

Ben Pope

Tom said:
What would be the best way to proceed?
Should I make a pure virtual class and then
derive from that? I want the base class to have
functions defined so that I don't have to do the
work all over again in the derived class. Is this
not what objects are for?
Please illuminate on how to do this properly.
I don't want code, just a pointer on how to
do the job right.
Any comments or links will help.

The C code is OpenGL. I just want a class
to make life easier for future projects.
If requested, I can send the source code done
up to now. I do not believe in wasting space, so
it is not in this post.



Just a quick example of wrapping an existing library and RAII:

// Keep the old library hidden
namespace libraryImpl {
# include "library.h"
}

// create a namespace for the library
namespace library {
class MyWrapper {
// Do Initialisation in Constructor
MyWrapper() { libraryImpl::init(); }

// Do Deinitialisation in destructor
~MyWrapper() { libraryImpl::deInit(); }

// Wrap functions that rely on above initialisation
DoSomething() { libraryImpl::DoSomething(); }
};

// Perhaps this does not rely on the initialisation
FreeFunction() { libraryImpl::FreeFunction(); }
}

int main() {
library::MyWrapper lib;

lib.DoSomething();

library::FreeFunction();
}


I'm sure you get the idea.

Ben Pope
 
J

Jonathan Mcdougall

Ben said:
Just a quick example of wrapping an existing library and RAII:

// Keep the old library hidden
namespace libraryImpl {
# include "library.h"
}

This won't work if the functions were defined in another namespace than
libraryImpl (as they probably will). libraryImpl::f() is *not* ::f()!
// create a namespace for the library
namespace library {
class MyWrapper {
// Do Initialisation in Constructor
MyWrapper() { libraryImpl::init(); }

// Do Deinitialisation in destructor
~MyWrapper() { libraryImpl::deInit(); }

// Wrap functions that rely on above initialisation
DoSomething() { libraryImpl::DoSomething(); }
};

// Perhaps this does not rely on the initialisation
FreeFunction() { libraryImpl::FreeFunction(); }
}

int main() {
library::MyWrapper lib;

lib.DoSomething();

library::FreeFunction();
}


I'm sure you get the idea.


Jonathan
 
B

Ben Pope

Jonathan said:
This won't work if the functions were defined in another namespace than
libraryImpl (as they probably will). libraryImpl::f() is *not* ::f()!

Yeah, I did think about this after posting. I've seen the same problem
when including windows.h.

Presumably it doesn't matter if you #include from the source file and
bring everything into the global namespace as it's local to the
translation unit anyway.

Header
--
namespace library {
class MyWrapper{
...
};
}


Source
--
#include "wrappedLibrary.h"

namespace library {
MyWrapper::MyWrapper ...
}


Ben Pope
 
J

Jonathan Mcdougall

Ben said:
Yeah, I did think about this after posting. I've seen the same problem
when including windows.h.

Presumably it doesn't matter if you #include from the source file and
bring everything into the global namespace as it's local to the
translation unit anyway.

When wrapping a library in a class, it is common to need member objects
defined by that library.

# include "the library"

class Wrapper
{
public:

private:
LibraryStruct s;
};

The problem here is that you have no choice but to include the library
header in the wrapper's header, making it visible to users. You could
make "s" a pointer and only declare LibraryStruct,

// don't need that anymore
// # include "the library"

class LibraryStruct;

class Wrapper
{
public:

private:
LibraryStruct *s;
};

but that could also mean some problems, for example if another version
of the library changes LibraryStruct to be a typedef of a template
(such as std::string).

The usual solution would be to use the "pimpl" idiom (or the Bridge
pattern).

// w.h
# include <memory>

class WrapperImpl;

namespace N
{

class Wrapper
{
public:
Wrapper();

private:
std::auto_ptr<WrapperImpl> impl_;
};

}

// w.cpp
# include "w.h"
# include "the library" // clients don't know about it

namespace N
{

class WrapperImpl
{
public:
LibraryStruct s;
};

Wrapper::Wrapper()
: impl_(new WrapperImpl)
{
library_init(&impl_->s);
}

}

Jonathan
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top