Jim,
Glad to see you are looking in to adding C++ to a C project. Without
going into the issues related to seperate compilers, I'm going to assume
you are using the GCC tool chain to compile both the C & C++ code. That
being the case, some example code follows after your questions. The
basic thing to take away is that you are compiling a C interface to your
C++ library, then linking your application with the g++ linker.
James Vanns wrote:
Sounds nasty doesn't it!! Well it's kinda what I need to do! I have an
external C struct (external to the C++ project/classes etc.) which is
wants a function ptr assigned to one of it's members:
struct blah {
int (func_ptr*) (int a, int b, float c);
}; etc...
However, my code is in C++ and a wish to assign a non-static member
function (I know I can do this) to this struct member! Can this be
done!? Some how with pointers or references? What about the STL's
mem_func stuff?
Can anyone shed some light on this?
Cheers
Jim
First, lets define a simple C++ class in a header file:
//simple.h A simple C++ class
//
#include <string>
#include <complex>
using namespace std;
class simple{
public:
simple();
int func1( int flags );
int func2(string s, complex<double> c);
friend simple operator+(const simple&, const simple&);
private:
int member1;
double member2;
string member3;
};
Next, lets define the class:
//simple++.C implementation file
#include "simple.h"
simple::simple(){
member1 = 0;
member2 = 0;
member3 = "This is a dummy string";
}
int simple::func1(int flags){
member1 |= flags;
return member1;
}
int simple::func2(string s, complex<double> c){
member3 = s;
member2 = c.real();
return (int)member2;
}
simple operator+(const simple& lhs, const simple& rhs){
simple tempvar;
return tempvar;
}
Ok, now lets wrap it in some C code that will be compiled with the C++
compiler, to start, we'll describe the interface in a header:
//simple_api.h C API simple class
#ifdef __cplusplus
extern "C" {
#endif
//Do everything through a pointer
typedef void* SIMPLE_HANDLE;
//The equavalent of new();
SIMPLE_HANDLE Screate();
//The equavalent of delete();
void sfree(SIMPLE_HANDLE sh);
//the first function
int sfunc1(SIMPLE_HANDLE sh, int flags);
//the second function
int sfunc2(SIMPLE_HANDLE sh, const char *s, double re, double im);
//the overloaded operator
void sadd(SIMPLE_HANDLE sh,
SIMPLE_HANDLE const lhs, SIMPLE_HANDLE const rhs);
#ifdef __cplusplus
}
#endif
Then, we'll implement it in a ".c" file:
//simple_api.c
#include "simple_api.h"
#include "simple.h"
extern "C"{
SIMPLE_HANDLE Screate(){ return new simple; }
void sfree(SIMPLE_HANDLE sh){ delete static_cast<simple*>(sh);}
int sfunc1(SIMPLE_HANDLE sh, int flags){
return static_cast<simple*>(sh)->func1(flags);
}
int sfunc2(SIMPLE_HANDLE sh, const char *s, double re, double im){
complex<double> cd(re, im);
return static_cast<simple*>(sh)->func2(s, cd);
}
void sadd(SIMPLE_HANDLE sh,
SIMPLE_HANDLE const lhs, SIMPLE_HANDLE const rhs){
*static_cast<simple*>(sh) = *static_cast<simple*>(lhs) +
*static_cast<simple*>(rhs);
}
}
And finally, we'll write an application in C which uses the C++ library
through the C code:
#include "simple_api.h"
int main(){
SIMPLE_HANDLE sh, sh2, sh3;
int flags = 1;
int retval = 0;
sh = Screate();
sh2 = Screate();
sh3 = Screate();
retval = sfunc1(sh, flags);
retval = sfunc2(sh, "Testing ...", 1, 2);
retval = sfunc1(sh2, flags);
retval = sfunc2(sh2, "Testing ...", 3, 4);
sadd(sh3, sh, sh2);
sfree(sh); /* Strictly speaking, not needed in this code example */
sfree(sh2); /* Strictly speaking, not needed in this code example */
sfree(sh3); /* Strictly speaking, not needed in this code example */
return 0;
}
Ok, all done, time to compile & link. The following log shows how my
make file did it:
[root@angus sample]# make
gcc -c sample.c
g++ -c simple_api.c
g++ -c simple++.C
g++ -O2 -o sample sample.o simple_api.o simple++.o