Passing a C++ object's member function to a C function expecing a function pointer!

J

James Vanns

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
 
J

Jeff Flinn

James,

James Vanns said:
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)

And how could that be?

The closest "non-static member function" would have the signature:

int (*fnc_ptr)( ThisClass*, int, int, float );

Where would the this pointer come from?
to this struct member! Can this be
done!? Some how with pointers or references? What about the STL's
mem_func stuff?

"mem_fun" results in a function object with an operator(), not even close to
a
static function pointer.
Can anyone shed some light on this?

The best you can do is to define a global or static function that uses a
global or static instance/reference/pointer to forward the call to it's
non-static member function with the passed in arguments.

The best approach depends on what your really trying to do. Perhaps you
could give more details as to what your attempting to do.

Jeff F
 
E

Evan Carew

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

David Harmon

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!

It's not what you don't know that hurts, it's what you know that isn't
so.

This issue is covered in Marshall Cline's C++ FAQ. See the topic
"[30.2] How do I pass a pointer to member function to a signal handler,
X event callback, etc?" It is always good to check the FAQ before
posting. You can get the FAQ at:
http://www.parashift.com/c++-faq-lite/
 
E

E. Robert Tisdale

David said:
This issue is covered in Marshall Cline's C++ FAQ.
See the topic "[30.2] How do I pass a pointer to member function
to a signal handler, X event callback, etc?"

# [30.2] What is "static typing,"
and how is it similar/dissimilar to Smalltalk?
 
R

red floyd

E. Robert Tisdale said:
David said:
This issue is covered in Marshall Cline's C++ FAQ.
See the topic "[30.2] How do I pass a pointer to member function
to a signal handler, X event callback, etc?"


# [30.2] What is "static typing,"
and how is it similar/dissimilar to Smalltalk?
It is always good to check the FAQ before posting.
You can get the FAQ at:

http://www.parashift.com/c++-faq-lite/

Yep. The topic they wanted was 33.2.
 
E

Evan Carew

red said:
E. Robert Tisdale said:
David said:
This issue is covered in Marshall Cline's C++ FAQ.
See the topic "[30.2] How do I pass a pointer to member function
to a signal handler, X event callback, etc?"



# [30.2] What is "static typing,"
and how is it similar/dissimilar to Smalltalk?
It is always good to check the FAQ before posting.
You can get the FAQ at:

http://www.parashift.com/c++-faq-lite/

Yep. The topic they wanted was 33.2.
Hmm... A pretty anemic example, don't you think?

Evan
 

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,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top