2

Im learning C++ at the moment, and am having some issues with casting pointers. In the first place I am not sure that what I am trying to do is what I want to do..

I am trying to take a function that can return the appropriate pointer to various method pointers based on string parameters, and to then use the method pointer.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;

typedef void* (*plugin_function)(void*);

static class Plugin
{
public:
    static bool doBoolStuff(){
        return true;// A Simple function that returns true
    }
};

void* getFunction(string pluginName, string functionName)
{
    if(pluginName =="Bool"){
        return &Plugin::doBoolStuff;
            //If the string is right it should return a method pointer.
            //I think that void* has the ability to point to anything, I am trying
            //to use that functionality to create a system where I am able to set 
            //some parameters and get the appropriate method pointer.
    }else{
        return NULL;
    }
}

int main(int argc, _TCHAR* argv[])
{
    void* pluginFunction;
    pluginFunction = getFunction("Bool","");

    if(pluginFunction == &Plugin::doBoolStuff)cout<<"CastSuccesful!"<<endl;

    //This section right here is where my code is breaking.
    //
    // IntelliSense: expression preceding parentheses of apparent call must have              
    //(pointer-to-) function type   
    //c:\Users\Walter\Dropbox\Inscription\MethodCasting\MethodCasting\MethodCasting.cpp 
    //MethodCasting

    cout << "Bool function ->"<< pluginFunction()<<endl;
    cout << "--------------------------------"<<endl;
    system("pause");

}

Any feedback would be helpful.

Paul R
  • 208,748
  • 37
  • 389
  • 560
robbert229
  • 464
  • 5
  • 12
  • Does `static class` compile? – Ed Heal Mar 03 '13 at 08:55
  • why not change the prototype of function void* getFunction(string pluginName, string functionName) to plugin_function getFunction(string pluginName, string functionName) – Adnan Akbar Mar 03 '13 at 08:57
  • Some possibly beneficial side reading on [nullptr.](http://stackoverflow.com/questions/1282295/what-exactly-is-nullptr) – ChiefTwoPencils Mar 03 '13 at 08:57
  • `void*` is not guaranteed to be able to point to anything. Formally it is limited to store pointers to data, not functions or member functions. It *does* work on many common systems, where all pointers *happen* to have the same size. – Bo Persson Mar 03 '13 at 09:06
  • @BoPersson Also, POSIX **requires** that `void *` be able to hold any pointer type (not sure if that applies to C++ too or C only, though.) –  Mar 03 '13 at 09:07
  • That's an additional requirement by the Posix standard. The language standards do not require this. – Bo Persson Mar 03 '13 at 09:08
  • @BoPersson pointers to member functions almost never have the same size as `void *` actually. this is a static function, though, so it's a normal function pointer. – Stephen Lin Mar 03 '13 at 09:09
  • My guess is that what you really should try is inheritance, with a virtual member function.. you can send what string you like to the factory function, and it can return a propeely typed pointer to the base class, which you can invoke the virtual member function from.. – Bingo Mar 03 '13 at 09:16
  • What you really want is to learn proper C++ idioms. Save low-level hacks such as pointer casting for much, much later – n. m. could be an AI Mar 03 '13 at 09:25

2 Answers2

2

Edit: Not true, sorry. As @Stephen Lin pointed out, I failed to read the static modifier... So while what you want doesn't work for non-static member functions, it usually does work for static members using reinterpret_cast (this behavior is implementation-defined):

class Plugin {
    public:
    static bool foo()
    {
        std::cout << "Foo called!" << std::endl;
        return true;
    }
};

void *get_func()
{
    return reinterpret_cast<void *>(&Plugin::foo);
}

int main()
{
    void *pluginFunction = get_func();
    (reinterpret_cast<bool (*)()>(pluginFunction))();
    return 0;
}

Original post:


You can't. According to this article:

However, there is no way to cast the void * back to a member function pointer that you could actually use.

I've tried it myself. Actually, all of static_cast, reinterpret_cast and even old C-style casts refused to work - neither with void *, nor with bool (*)() (yes, I've even tried to cast from a non-member function pointer type to a member function type)...

Sorry, C++ doesn't seem to allow us to do this.

  • This is a static function, so it's a normal function pointer, actually. – Stephen Lin Mar 03 '13 at 09:08
  • @StephenLin No, it's a class member function, so its address is a pointer to member function. –  Mar 03 '13 at 09:08
  • It is implementation defined in C++11: `Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cvqualification, shall yield the original pointer value.` – Jesse Good Mar 03 '13 at 09:09
  • @JesseGood Do you have some code? I'd be curious to see how it's possible (actually I'm quite disappointed because it seems to be impossible/disallowed). –  Mar 03 '13 at 09:10
  • @H2CO3 it's not a pointer to member function, there's no implicit `this` argument – Stephen Lin Mar 03 '13 at 09:12
  • @H2CO3, i think it's still implementation-defined if you can convert normal function pointers to `void *` [(cppreference)](http://en.cppreference.com/w/cpp/language/reinterpret_cast)...it'll work on POSIX though, and probably Windows. – Stephen Lin Mar 03 '13 at 09:30
  • @StephenLin Yes, that was already mentioned in the comments on the question by BoPersson. –  Mar 03 '13 at 09:34
  • @H2CO3, well, okay, but I think you should mention it in the answer. (it **will** usually work, though) – Stephen Lin Mar 03 '13 at 09:45
  • @StephenLin Done that as well. –  Mar 03 '13 at 09:53
0

It depends on your implementation, if you can do this. In portable C++ you can't. And even if you can, you need explicit casts (in this case reinterpret_cast<>) to convert between different pointer types.

Note that this does not extend to real "method" pointers, that is to non-static member function pointers. You cannot convert between member function pointers and either object pointers or ordinary function pointers. The approach I present at the end can be used, if you only have non-static member function pointers.

Portably reinterpret_cast<> can freely convert between function pointer types and object pointer types - although any use of the result except conversion back to the original type is undefined in almost all cases.

For conversions between object pointer types and function pointer types, the C++11 standard says (§5.2.10 [expr.reinterpret.cast]/8):

Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv- qualification, shall yield the original pointer value.

So, it depends on your implementation (and should be documented in its documentation), if casting a function pointer to a void * compiles and back compiles at all. Alas, if it does, you should get the expected behavior.

In your code the casts are missing. You need a cast to the generic type (in your case void*) in getFunction and you need to cast back to the original type in order to call the function. So you will need to know the original type in main():

void* pluginFunction = getFunction("Bool","");
// ....
cout << "Bool function ->"<< (reinterpret_cast<bool (*)()>(pluginFunction))()<<endl;

A more portable solution would be to use an arbitrary function pointer type, for example void (*)() to pass plugin function pointers around, so that you have:

typedef void (*any_func_ptr)();

// If you wanted to use this for non-static member functions, you could do
//   struct AnyClass;
//   typedef void (AnyClass::*any_memfun_ptr)();

any_func_ptr getFunction(string pluginName, string functionName)
{
    if(pluginName =="Bool"){
        return reinterpret_cast<any_func_ptr>(&Plugin::doBoolStuff);
    }else{
        return NULL;
    }
}

int main(int argc, char* argv[])
{
    any_func_ptr pluginFunction = getFunction("Bool","");

    if(reinterpret_cast<bool (*)()>(pluginFunction) == 
         &Plugin::doBoolStuff)
             cout<<"CastSuccesful!"<<endl;

    cout << "Bool function ->"<< (reinterpret_cast<bool (*)()>(pluginFunction))()<<endl;

}
JoergB
  • 4,383
  • 21
  • 19