By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,864 Members | 1,285 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,864 IT Pros & Developers. It's quick & easy.

problem with function pointers

P: n/a
I have two classes:
class OntologyParser
{
...

protected:

virtual void startElement(void *userData, const char *name, const
char **atts);
virtual void endElement(void *userData, const char *name);
virtual void charData( void *userData, const XML_Char *s, int len );

....
public:
void initXMLParse(const string& fname);
.....
};

This class is a base class for

class ProtegeOntologyParser : public OntologyParser
{
public:
inline ProtegeOntologyParser(const string& strFileName)
{
initXMLParse(strFileName);
}

};

I am using G++ on RedHat 9.0 Linux with Expat library.

The initXMLParse function is common to all (here just
ProtegeOntologyParser) derived classes hence I want to keep that in
parent class. The functions startElement, endElement and charData must
be implemented separately by all derived classes.

However the problem is expat needs call backs setup for startElement,
endElement and charData functions from within initXMLParse like this:

void OntologyParser::initXMLParse(const string& fname)
{
char buffer[BUFSIZ];
int len;
int done;
int depth = 0;

//Get the Parser
XML_Parser parser = XML_ParserCreate(NULL);

//User Data Handler
XML_SetUserData(parser, &depth);

//Element Level Handler
XML_SetElementHandler(parser, startElement, endElement);

//Set What to do with the data
XML_SetCharacterDataHandler( parser, charData );

....
}

But the functions that I pass there as argument must be the functions
of derived classes and right function addresses should be passed based
upon which object was responsible for invoking initXMLParse().

As you know ISO C++ forbids somthing like &(this->charData)
Secondly i do not want to make those 3 function static. and they must
be "virtual" in the base class so that all derived classes are forced
to implement them.

How can I pass those arguments?

Jul 23 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
"TheOne" <su****************@gmail.com> wrote...
I have two classes:
class OntologyParser
{
...

protected:

virtual void startElement(void *userData, const char *name, const
char **atts);
virtual void endElement(void *userData, const char *name);
virtual void charData( void *userData, const XML_Char *s, int len );

....
public:
void initXMLParse(const string& fname);
.....
};

This class is a base class for

class ProtegeOntologyParser : public OntologyParser
{
public:
inline ProtegeOntologyParser(const string& strFileName)
{
initXMLParse(strFileName);
}

};

I am using G++ on RedHat 9.0 Linux with Expat library.

The initXMLParse function is common to all (here just
ProtegeOntologyParser) derived classes hence I want to keep that in
parent class. The functions startElement, endElement and charData must
be implemented separately by all derived classes.

However the problem is expat needs call backs setup for startElement,
endElement and charData functions from within initXMLParse like this:

void OntologyParser::initXMLParse(const string& fname)
{
char buffer[BUFSIZ];
int len;
int done;
int depth = 0;

//Get the Parser
XML_Parser parser = XML_ParserCreate(NULL);

//User Data Handler
XML_SetUserData(parser, &depth);

//Element Level Handler
XML_SetElementHandler(parser, startElement, endElement);

//Set What to do with the data
XML_SetCharacterDataHandler( parser, charData );

....
}

But the functions that I pass there as argument must be the functions
of derived classes and right function addresses should be passed based
upon which object was responsible for invoking initXMLParse().

As you know ISO C++ forbids somthing like &(this->charData)
Secondly i do not want to make those 3 function static.
But how would expat call them? It requres them to be callbacks of some
particular signature which probably does not have anything to do with
your classes. You have no choice but to make them static.
and they must
be "virtual" in the base class so that all derived classes are forced
to implement them.
The derived classes are not going to be forced unless those functions
are declared pure.
How can I pass those arguments?


Make the three functions static. Let expat pass the 'userdata' as
void* and static_cast it to your base class in each function. Then
call your "real" processing functions, which should be virtual, using
that base class pointer. The derived function should be called.

---------------------------------------
struct Caller { // your expat emulator
void (*int_callback)(void*,int);
void (*double_callback)(void*,double);
void* ptr;

void init_ptr(void* p) { ptr = p; }
void init_int_cb(void (*icb)(void*,int)) { int_callback = icb; }
void init_dbl_cb(void (*dcb)(void*,double)) { double_callback =
dcb; }

void do_something() {
int_callback(ptr, 666);
double_callback(ptr, 3.1415926);
int_callback(ptr, 42);
}
};

struct Base {
Caller *caller;

Base() : caller(new Caller) { caller->init_ptr(this); }
virtual ~Base() { delete caller; }
Base(const Base& b) : caller(new Caller(*b.caller)) {}

void init_caller();

static void foo_callback(void*, int);
static void bar_callback(void*, double);
virtual void foo(int) = 0;
virtual void bar(double) = 0;

private:
Base& operator =(const Base&);
};

#include <iostream>
using std::cout;

struct Derived : Base {
virtual void foo(int a) { cout << "Derived::foo(" << a << ")\n"; }
virtual void bar(double d) { cout << "Derived::bar(" << d <<
")\n"; }
};

void Base::foo_callback(void* ptr, int a) {
Base *p = static_cast<Base*>(ptr);
p->foo(a);
}

void Base::bar_callback(void* ptr, double d) {
Base *p = static_cast<Base*>(ptr);
p->bar(d);
}

void Base::init_caller() {
caller->init_int_cb(foo_callback);
caller->init_dbl_cb(bar_callback);

caller->do_something();
}

int main() {
Base *pb = new Derived;
pb->init_caller();
delete pb;
}
---------------------------------------
V
Jul 23 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.