0

So it seems ANTLR3C uses function pointers to allow users to override them if we want to write our own functions. I need to override the error reporting function:

Pointer

void(*displayRecognitionError)(struct ANTLR3_BASE_RECOGNIZER_struct * recognizer,
                                 pANTLR3_UINT8 * tokenNames);

Function

static void displayRecognitionError (pANTLR3_BASE_RECOGNIZER recognizer,
                                     pANTLR3_UINT8 * tokenNames);

Right now I have the following:

@lexer::apifuncs {
  RECOGNIZER->displayRecognitionError = displayRecognitionErrorNew;
}

@lexer::includes {
  #include "lexerData.h"

  static void displayRecognitionErrorNew (pANTLR3_BASE_RECOGNIZER recognizer,
                                          pANTLR3_UINT8 * tokenNames);
}

@lexer::members {
  #include "lexerError.h"
}

with the new error code(which all works) in the file lexerError.h. I'm trying to change this by moving the error function inside the lexerData class but unfortunately I get a compile error when try to set the function pointer to the class member.

compileUnit.cpp:179:62: error: argument of type ‘void (lexerData::)(ANTLR3_BASE_RECOGNIZER_struct*, uint8_t**)’ does not match ‘void (*)(ANTLR3_BASE_RECOGNIZER_struct*, uint8_t**)’

From what I've read this isn't a simple casting or syntax problem. What should I do to allow this? One fix appears to be change the function pointer definition but I need to able to assign the function pointer to different classes as the lexer is run twice with different data structures.

3 Answers3

1

Generally, it is not possible to simply assign address of member non-static function to pointer to non-class function. You can create non-class function which will call the proper member function of the lexerData class. The problem is that this non-class function must be able to reference the lexerData object in some way. I don't know anything about ANTLR3C so, unfortunately, I can't give you a specific advice about that :(

tomac
  • 66
  • 3
  • As you suggested, I ended up with a static global function that tests a boolean and selects the appropriate class function the call. Thanks! –  Mar 10 '11 at 04:55
1

The answer lies within this question.

Also boost::bind may help you. I do not have much information about it though.

Community
  • 1
  • 1
ali_bahoo
  • 4,732
  • 6
  • 41
  • 63
  • Thanks for that link. Sadly I don't know how to use templates but I think I see what it is doing. The codeproject page is very helpful. –  Mar 09 '11 at 16:26
0

In C++ each member function of the class has a hidden parameter. It is a pointer to the instance of the class (this). The implementation of this feature is not standardized, so you cannot assume that this parameter can be somehow "found" with some specific signature like int foo(const MyClass*, int, int); instead of int foo(int, int); for the class MyClass.

Generally this means that if you have a member function of some class and want to have a pointer to it, you have a problem. I remember that in one project we used C macros + the table of methods and classes was used to convert "pointers" to functions to real calls to functions. The general idea was to "register" the instance of the class with macro in some global table and later to call the method of the class using the additional dispatch via this table.

avp
  • 4,895
  • 4
  • 28
  • 40