2

I am working on code that needs to send a member function pointer to a logger method that accepts a void * as the parameter. I cannot change it from void *. I cannot use c++11 either. Is there a way to get it to work without any warning. For example:

logger.h

    #ifndef _LOGGER_H
    #define _LOGGER_H

    void logger( void *func );

    #endif /* _LOGGER_H */

logger.cpp

    #include <cstdio>
    #include "logger.h"

    void logger( void *func )
    {
        printf("%lx\n", (unsigned long)func);
    }

testCase.cpp

    #include "logger.h"

    class myClass
    {
        public:
            void testCase( void );
    };

    void myClass::testCase( void )
    {
        /* This works on my compiler, but gives warning */
        /* warning: converting from 'void (myClass::*)()' to 'void*' */
        /* I know this is bad and wrong. */
        logger((void *)&myClass::testCase);

        /* This compiles without warning */
        /* But doesnt work the way I need, gives ffff*/
        void (myClass::*ptr)( void ) = &myClass::testCase;
        void *m_ptr = ptr;
        logger(m_ptr);
    }

logger.h and logger.cpp cannot be changed.

This is being run a VxWorks and I need the address to look up in the symbol table. When I try the second way I get ffff. Although I get a real address when using other compilers, its different for VxWorks.

Can you think of another way to get this to work.

References

Community
  • 1
  • 1
  • You could pass a pointer a struct containing a member function pointer, or have it point to an address which contains a member function pointer (which are pretty much the same, one with more syntax sugar) – OMGtechy Mar 16 '16 at 16:07

2 Answers2

3

No, you can't make it happen. Standard prohibits converting pointers-to-members to void*. The reason for this is their incompatibility with void* - they are usually double the size of the void*.

Your code has other issues as well, for example, (unsigned long)func is converting a void* to unsigned long, and this is undefined as well. For example, on many systems long is 32 bits in length, while void* is 64bit. To reliably convert void* to integer type, you need to use uintptr_t (provided your implementation has it).

SergeyA
  • 56,524
  • 5
  • 61
  • 116
  • The original code passed the member function as a string "myClass::testCase" and that was converted to the unsigned long. We are trying to get rid of the old way and implement a new service. passing a member function pointer to a logger. The logger code was written in c and cannot be changed because it is being used in so many other places. We wanted to find a way to pass the pointer. – Tyler Gajewski Mar 16 '16 at 14:25
  • @TylerGajewski, like I said, firstly you can't. Secondly, imagine you do it. What are you going to do with this pointer in C logger? – SergeyA Mar 16 '16 at 14:29
  • The actual logger is 2400 lines long so i simplified it a bit. But ideally it doesn't use printf it uses the registers to print to a vx console and the user would use that address to look up in the symbol table. The logger also accepts an ellipsis and format to output a string for debugging to the console. So the output would be something like: `5649b0(This is a message)` Where then the user could copy that address and use it to look up in the symbol table. The code get very complicated – Tyler Gajewski Mar 16 '16 at 14:35
  • @TylerGajewski, you would have very hard time looking up pointer to member in the symbol table. Do not forget about virtual functions! – SergeyA Mar 16 '16 at 14:38
  • My lead says that if we could get it to work even with the virtual function issue then it would still be an improvement over what we have. The implementation i have with the first example works exactly like we want it to. But where I work it is illegal to have warnings. – Tyler Gajewski Mar 16 '16 at 14:41
  • If I was able to change the logger to accept a member function pointer. Could it be done if the logger is not in the same class as the calling function. ex. `void logger( void (class::*)( void ) )` could the class be generic? ie. could it accept any class. – Tyler Gajewski Mar 16 '16 at 14:48
  • @TylerGajewski, you'd have to make your logger a template for this. – SergeyA Mar 16 '16 at 15:11
  • I wish i was allowed to use a template. But were using a very very old gcc compiler and templates aren't allowed. Thank you for your help @SergeyA – Tyler Gajewski Mar 16 '16 at 15:17
1

I don't know about "double the size"; pointers are pointers and in my understanding, all pointers on a given system are the same size, regardless of what they point to...

However, looking in my copy of The C++ Programming Language, 3rd Edition, by Stroustrup (page 101):

Occurrances of void*s at higher levers of the system should be viewed with suspicion because they are likely indicators of design errors. Where used for optimization, void* can be hidden behind a type safe interface (§13.5, §24.4.2).

Pointers to functions (§7.7) and pointers to members (§15.5) cannot be assigned to void*s.

Community
  • 1
  • 1
cvanbrederode
  • 354
  • 3
  • 10
  • You should remove the first part about all pointers being the same size; it's not true; member function pointers can be and usually are bigger than "standard" pointers. You learn something every day! – OMGtechy Mar 16 '16 at 16:05
  • Your first sentence is plain wrong, you better remove it. – SergeyA Mar 16 '16 at 16:11