2017-01-24 11 views
0

Я пытаюсь на карте boost::functions. Поэтому я могу назвать их строковым именем с параметрами ввода и вывода.Отправить переменную в указатель void или ссылку на указатель void в C++

Пример:

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

Я хотел бы создать входные и выходные переменные, и послать их указатели на MyFuncs::CallFunc() быть обработаны.

Я могу послать (void* input) указатель в функцию, и извлечь его значение в целое, строка и т.д.

Я не могу отправить (void* output), что выделяет его собственное пространство, чтобы получить значение. Я должен создать new type(var) внутри вызываемой функции, или переменная выйдет из области действия после возвращения функции.

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

В C++ 17, вы хотите, чтобы исследовать использование [ 'станд :: any'] (HTTP://en.cppreference.com/w/cpp/utility/any), а не 'void *'. Вы можете использовать версию Boost до того, как C++ 17 официально выйдет – WhiZTiM

+0

@WhiZTiM Спасибо за быстрый ответ .. исследуя сейчас. – aquawicket

+0

Opps. Я все еще на C++ 98 из-за некоторых кросс-платформенных особенностей. Кроме того, почему я все еще использую boost здесь. std :: все еще не будут доступны мне. – aquawicket

ответ

0

РЕШЕНИЕ
без использования static_cast или дополнительные функции подталкивания, я был в состоянии использовать чистый C++.

*(int*)output = var; и *(std::string*)output = var; похоже, делают трюк.


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.ч

#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 объявляется внутри main. Для того чтобы out был действительным, он должен указывать на то, чье время жизни по крайней мере равно main. Поскольку вы не объявили данных членов типа int и string внутри вашего класса MyClass, которые могут быть возвращены через out, вам необходимо выделить память.

Предположим, вы объявили член int var; данных в классе MyClass тогда GetNumber будет выглядеть так:

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

Это может сработать, но если на какой-то момент я попаду в несколько потоков, это может взорваться. Я хотел бы создать выходную переменную за пределами класса, который я вызываю. – aquawicket

+1

@aquawicket: Тогда в этом случае вы можете просто выполнить 'int out_int; void * out = (void *) & out_int; 'и' GetNumber (void * input, void * output) {* output = what_ever_int_value_you_like; '} – sameerkn

+0

' GetNumber (void * input, void * output) {int num = 69; * output = num; } '* output - это незаконная косвенность, независимо от того, что я ему назначаю. – aquawicket