2017-01-24 1 views
0

J'essaye la carte boost::functions. Je peux donc les appeler par un nom de chaîne, avec des paramètres d'entrée et de sortie.Envoie une variable dans un pointeur vide, ou une référence de pointeur vide en C++

Exemple:

MyFuncs::CallFunc("MyClass::TestFunc", void* input, void* output); 

Je voudrais créer les variables d'entrée et de sortie, et envoyer un de leurs pointeurs à MyFuncs::CallFunc() à traiter.

je peux envoyer un pointeur (void* input) dans la fonction, et extraire sa valeur int, string, etc.

Je ne peux pas envoyer un (void* output) qui attribue son propre espace pour recevoir une valeur. Je dois créer un new type(var) à l'intérieur de la fonction appelée, sinon la variable sortira de la portée une fois la fonction retournée.

MyFuncs.h

//MyFuncs.h 
#include <boost/function.hpp> 
#include <boost/bind.hpp> 
#include <map> 

class MyFuncs 
{ 
public: 

    static std::map<std::string, boost::function<void (void*, void*&)> > myfuncs; 

    template<class T> 
    static void RegisterFunc(const std::string& name, void (T::*func) (void*, void*&), T* instance) 
    { 
     myfuncs[name] = boost::bind(func, instance, _1, _2); 
    } 

    static void CallFunc(const std::string& name, void* input, void*& output) 
    { 
     myfuncs[name](input, output); 
    } 
}; 

std::map<std::string, boost::function<void (void*, void*&)> > MyFuncs::myfuncs; 


MyClass.h

//MyClass.h 
#include "MyFuncs.h" 

class MyClass 
{ 
public: 
    MyClass() 
    { 
     MyFuncs::RegisterFunc("MyClass::GetNumber", &MyClass::GetNumber, this); 
     MyFuncs::RegisterFunc("MyClass::GetString", &MyClass::GetString, this); 
     MyFuncs::RegisterFunc("MyClass::EditNumber", &MyClass::EditNumber, this); 
     MyFuncs::RegisterFunc("MyClass::EditString", &MyClass::EditString, this); 
    } 

    void GetNumber(void* input, void*& output) 
    { 
     int var = 1234; 
     output = static_cast<void*>(new int(var));    //WORKS, var eats memory 
     //output = static_cast<void*>(&var);     //ERROR, var goes out of scope 
    } 

    void GetString(void* input, void*& output) 
    { 
     std::string var = "Get test"; 
     output = static_cast<void*>(new std::string(var));  //WORKS, var eats memory 
     //output = static_cast<void*>(&var);     //ERROR, var goes out of scope 
    } 

    void EditNumber(void* input, void*& output) 
    { 
     int var = *static_cast<int*>(input);     //WORKS, var gets 4321 OK 
     output = static_cast<void*>(new int(var));    //WORKS, var eats memory 
     //output = static_cast<void*>(&var);     //ERROR, var goes out of scope 
    } 

    void EditString(void* input, void*& output) 
    { 
     std::string var = *static_cast<std::string*>(input); //WORKS, var gets "Edit test" OK 
     output = static_cast<void*>(new std::string(var));  //WORKS, var eats memory 
     //output = static_cast<void*>(&var);     //ERROR, var goes out of scope 
    } 
}; 


MyApp.cpp

//MyApp.cpp 
#include "MyClass.h" 

void main() 
{ 
    MyClass myclass; 

    void* in; 
    void* out; 

    MyFuncs::CallFunc("MyClass::GetNumber", NULL, out); //atempting to fill the variable 
    int getNumOut = *static_cast<int*>(out); 
    printf("MyClass::GetNumber = %d \n", getNumOut); 

    MyFuncs::CallFunc("MyClass::GetString", NULL, out); //atempting to fill the variable 
    std::string getStrOut = *static_cast<std::string*>(out); 
    printf("MyClass::GetString = %s \n", getStrOut.c_str()); 

    int editNum = 4321; 
    in = static_cast<void*>(&editNum); 
    MyFuncs::CallFunc("MyClass::EditNumber", in, out); //atempting to fill the variable 
    int editNumOut = *static_cast<int*>(out); 
    printf("MyClass::EditNumber = %d \n", editNumOut); 

    std::string editStr = "Edit test"; 
    in = static_cast<void*>(&editStr); 
    MyFuncs::CallFunc("MyClass::EditString", in, out); //atempting to fill the variable 
    std::string editStrOut = *static_cast<std::string*>(out); 
    printf("MyClass::EditString = %s \n", editStrOut.c_str()); 

    getchar(); //wait for close 
} 
+2

En C++ 17, vous voulez explorer l'utilisation de [ 'std :: any'] (http://en.cppreference.com/w/cpp/utility/any) plutôt que "void *". Vous pouvez utiliser la version Boost avant le lancement officiel de C++ 17 – WhiZTiM

+0

@WhiZTiM Merci pour la réponse rapide .. recherche maintenant. – aquawicket

+0

Opps. Je suis toujours au C++ 98 en raison de certaines spécificités multiplateformes. Aussi pourquoi j'utilise encore boost ici. std :: tout ne sera pas encore disponible. – aquawicket

Répondre

0

SOLUTION
Sans utiliser static_cast ou fonctions coup de pouce supplémentaire, je suis en mesure d'utiliser C++ pur.

*(int*)output = var; et *(std::string*)output = var; semblent faire l'affaire.


MyFuncs.h

#include <boost/function.hpp> 
#include <boost/bind.hpp> 
#include <map> 

class MyFuncs 
{ 
public: 

    //A list of function names linked to boost::functions. 
    static std::map<std::string, boost::function<void (void*, void*)> > myfuncs; 


    //Register a class function by name.  MyFuncs::RegisterFunc("MyClass::Test", &MyClass::Test, instance); 
    template<class T> 
    static void RegisterFunc(const std::string& name, void (T::*func) (void*, void*), T* instance) 
    { 
     myfuncs[name] = boost::bind(func, instance, _1, _2); 
    } 


    //Call functions by name, with input and output.  MyFunct::CallFunc("MyClass::Test", input, output); 
    static void CallFunc(const std::string& name, void* input, void* output) 
    { 
     myfuncs[name](input, output); 
    } 
}; 

std::map<std::string, boost::function<void (void*, void*)> > MyFuncs::myfuncs; 



MyClass.h

#include "MyFuncs.h" 

class MyClass 
{ 
public: 
    MyClass() 
    { 
     MyFuncs::RegisterFunc("MyClass::GetNumber", &MyClass::GetNumber, this); 
     MyFuncs::RegisterFunc("MyClass::GetString", &MyClass::GetString, this); 
     MyFuncs::RegisterFunc("MyClass::EditNumber", &MyClass::EditNumber, this); 
     MyFuncs::RegisterFunc("MyClass::EditString", &MyClass::EditString, this); 
    } 

    void GetNumber(void* input, void* output) 
    { 
     int var = 1234; 
     *(int*)output = var; 
    } 

    void GetString(void* input, void* output) 
    { 
     std::string var = "Get test"; 
     *(std::string*)output = var; 
    } 

    void EditNumber(void* input, void* output) 
    { 
     int in = *(int*)input; //4321 
     int out = in - 4320; //result is 1; 
     *(int*)output = out; 
    } 

    void EditString(void* input, void* output) 
    { 
     std::string in = *(std::string*)input; //"Edit Test" 
     std::string out = in += " (edited)"; //result is "Edit test (edited)" 
     *(std::string*)output = out; 
    } 
}; 



MyApp.cpp

#include "MyClass.h" 

void main() 
{ 
    MyClass myclass; 

    int getNum; 
    MyFuncs::CallFunc("MyClass::GetNumber", NULL, &getNum); 
    printf("MyClass::GetNumber = %d \n", getNum); 

    std::string getStr; 
    MyFuncs::CallFunc("MyClass::GetString", NULL, &getStr); 
    printf("MyClass::GetString = %s \n", getStr.c_str()); 

    int editNumIn = 4321; 
    int editNumOut; 
    MyFuncs::CallFunc("MyClass::EditNumber", &editNumIn, &editNumOut); 
    printf("MyClass::EditNumber = %d \n", editNumOut); 

    std::string editStrIn = "Edit test"; 
    std::string editStrOut; 
    MyFuncs::CallFunc("MyClass::EditString", &editStrIn, &editStrOut); 
    printf("MyClass::EditString = %s \n", editStrOut.c_str()); 

    getchar(); //wait for close 
} 
1

void* out est déclarée à l'intérieur main. Pour out être valide, il devrait pointer vers quelque chose dont la durée de vie est au moins celle de main. Puisque vous n'avez pas déclaré les membres de données de type int et string dans votre classe MyClass qui peut être renvoyé via out, vous devez donc allouer de la mémoire.

Supposons que vous avez déclaré des données membre int var; en classe MyClass alors GetNumber ressemblerait à ceci:

class MyClass 
{ 
    private: 
      int var; 

    public: 
    MyClass() 
    { 
     //Register function 
     var = 10; 
    } 

    void GetNumber(void* input, void*& output) 
    { 
     //int var = 1234; //<-- instead of using local "var", now use MyClass::var i.e this->var 
     output = static_cast<void*>(&(this->var)); 
    } 
}; 
+0

Cela pourrait fonctionner, mais si pour un peu de chance je reçois plusieurs threads, il pourrait exploser. Je voudrais créer la variable de sortie en dehors de la classe que j'appelle. – aquawicket

+1

@aquawicket: Dans ce cas, vous pouvez simplement faire 'int out_int; void * out = (void *) & out_int; 'et' GetNumber (entrée void *, sortie void *) {* output = what_ever_int_value_you_like;}} – sameerkn

+0

'GetNumber (entrée void *, void * output) {int num = 69; * sortie = num; } '* output est une indirection illégale, peu importe ce que je lui assigne. – aquawicket