Thread: Casting a pointer to a function to (void*)

  1. #1
    Registered User
    Join Date
    Jan 2009
    Posts
    7

    Casting a pointer to a function to (void*)

    I have a pointer to a function in a class, and am trying to cast it to (void*) to pass it to a function.

    Code:
    #include <stdio.h>
    
    class blah {
       public:
          int store;
          int something (int in);
    };
    
    int blah::something (int in) {
       store = in;
    }
    
    void print (void*in) {
       printf ("%lx\n", in);
    }
    
    int (blah::*pt2Member)(int);
    
    int main () {
       pt2Member = &blah::something;
    // printf ("%lx\n", pt2Member);
    // print ((void*)pt2Member);
       print ((void*)blah::something);
    }
    When trying to cast it to (void*) when passing it to print, gcc complains:
    test.cpp: In function 'int main()':
    test.cpp:24: error: invalid use of non-static member function 'int blah::something(int)'

    Calling the printf works fine, presumably because it uses va_arg.

  2. #2
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    You can't cast function pointer or member pointer to void pointer. It's not allowed by the language, because in some architectures the two types are incompatible.

    I don't think there is any standard permitted way to print the value of a function or method pointer. However, casting to long is what you must do, if you are using %lx.

    Speaking of which why are you using printf instead of cout?
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  3. #3
    Registered User
    Join Date
    Jan 2009
    Posts
    7
    Thats what I was afraid of. And I was using printf because I know C very well, and I wrote this quickly, and printf was just easier. Anyway I thought of a hack that will work, I think.

  4. #4
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Doing the following should work on 32 bit architectures, I think:
    Code:
    printf( "%lx\n", reinterpret_cast<long>(pt2Member) );
    Or with cout:
    Code:
    cout << hex << reinterpret_cast<unsigned long>(pt2Member);
    Last edited by King Mir; 01-17-2009 at 05:00 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  5. #5
    Registered User
    Join Date
    Jan 2009
    Posts
    7
    No that doesn't work, but I am on amd64. A pointer is still the same size as unsigned long, however, on both architectures, I'm pretty sure.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    OK, wait just a moment. There are two errors in your program.

    One is a small syntax error that causes your current problem: You always have to use & to take the address of a member function, and you're not doing it in the printf call that's not commented out.

    The other is the idea that you can cast member function pointers to void* - or long, for that matter. Normal function pointers are one thing - while the standard doesn't allow you to cast them to object pointers, most architectures support it, and the pointers are the same size.
    Member function pointers on the other hand are totally incompatible. Their size is often larger than that of normal function pointers. Worse, it can vary! For example, on MSVC, a member function pointer is:
    1*sizeof(void*) if the class is defined and has a very simple inheritance chain.
    2*sizeof(void*) if the class is defined and its inheritance chain contains multiple inheritance.
    4*sizeof(void*) if the class is defined and its inheritance chain contains virtual inheritance.
    4*sizeof(void*) if the class is only declared. (That's because the compiler doesn't know its inheritance chain.)

    So, you really can cast member function pointers only to bool and to other member function pointers (don't call those!). Everything else is completely meaningless.


    By the way, long on amd64 systems is compiler-dependent. On GCC and imitating compilers, it's 64 bits wide. On MSVC and imitating compilers, it's 32 bits wide.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Jan 2009
    Posts
    7
    I'm obviously not too familiar with c++, I'm really coming from a C/assembly background, and use gcc.

    I'm dealing with a class thats as simple as the one above, and doesn't really deal with inheritance. I'm looking for the address that would be jumped to. I imagine that even when theres several different member functions due to inherritance, only one is actually called. I need the pointer to the function that is actually called.

    The address that "printf ("%lx\n", pt2Member);" prints out is the same as the address of blah::something that IDA shows.

    Either way, this is really just a test case to show the problem I'm having. I'm using llvm to generate code as a jit that calls a member function of a class. It is working fine, the problem is that its not practical to manually type in all the addresses of the functions into my code.

    I'm starting to understand why this isn't really supported. I'm thinking of something using dl_sym would work.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    So... under MSVC you can't cast between pointer-to-members of a different type? (I know you can't use them. I'm not asking that. I only wonder if the invocation "works" if you cast the result back to the correct type. I will not have a newish MSVC available to test this myself for a few days.)

    I think that GCC always uses '2 * sizeof(void *)' for pointer-to-member variables.

    "I need the pointer to the function that is actually called."

    No. You don't. You can't call a member function without an object of the correct type. Bypassing the restriction is guaranteed to break something eventually. With templates and macro magic you can arbitrarily wrap the method invocations in a safe and portable fashion.

    Soma
    Last edited by phantomotap; 01-17-2009 at 05:34 PM.

  9. #9
    Registered User
    Join Date
    Jan 2009
    Posts
    7
    I'm basically generating assembly at runtime, that is then immediately ran. At the lowest level, a c++ function has one additional arguement, a pointer to this instance of the object. The pointer to the object is easy enough to get, I just need to get the pointer to the member function. I can then create my assembly code that calls this member function. Its unlikely that the c++ abi will change dramatically, at least on linux, cause of headaches of broken libraries.

  10. #10
    Registered User
    Join Date
    Jan 2009
    Posts
    7
    For those interested, heres quite an ugly hack that does what I need:

    Code:
    inline void *get_address (int num, ...) {
       va_list args;
    
       va_start (args, num);
       return va_arg (args, void*);
    }
    use it like:
    Code:
    void *result = get_address (1, &blah::something);

  11. #11
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    how would you convert it back to call it?

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by genter View Post
    For those interested, heres quite an ugly hack that does what I need:
    It just takes the first word that's passed to the function and interprets it as a void*. This might work in extremely limited circumstances, but it will crash and burn when you change compiler or modify the class, without any warning whatsoever.

    Are you really that desperate to generate member calls at runtime?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    Registered User
    Join Date
    Jan 2009
    Posts
    7
    Quote Originally Posted by m37h0d View Post
    how would you convert it back to call it?
    I'm generating assembly that calls it. Look at some C++ code in a disassembler.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 04-04-2009, 03:45 AM
  2. Following CTools
    By EstateMatt in forum C Programming
    Replies: 5
    Last Post: 06-26-2008, 10:10 AM
  3. Replies: 7
    Last Post: 07-04-2007, 12:46 PM
  4. Glib and file manipulation
    By unixOZ in forum Linux Programming
    Replies: 1
    Last Post: 03-22-2004, 09:39 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM