【问题标题】:Send a variable into a void pointer, or a void pointer reference in C++将变量发送到 void 指针,或 C++ 中的 void 指针引用
【发布时间】:2017-01-24 09:57:06
【问题描述】:

我正在尝试映射boost::functions。所以我可以通过字符串名称来调用它们,带有输入和输出参数。

例子:

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

我想创建输入和输出变量,并将它们的指针发送到MyFuncs::CallFunc() 进行处理。

我可以将(void* input) 指针发送到函数中,并将其值提取到 int、string 等。

我无法发送分配它自己的空间来接收值的(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
}

【问题讨论】:

  • 在 C++17 中,您将希望探索使用 std::any 而不是 void*。在 C++17 正式推出之前,你可以使用 Boost 版本
  • @WhiZTiM 感谢您的快速回复.. 正在研究中。
  • 奥普斯。由于一些跨平台的细节,我仍在使用 c++98。还有为什么我仍然在这里使用 boost。我还不能使用 std::any。
  • 如何使用 Boost 版本,Boost.Any。它应该适用于 C++98。自 2001 年左右以来一直在 Boost 中......
  • 我刚刚阅读了您关于 boost 提供等同于 std::any 的 std 的更新评论。现在研究。非常感谢

标签: c++ pointers boost reference void-pointers


【解决方案1】:

void* outmain 中声明。要使out 有效,它应该指向生命周期至少为main 的东西。由于您没有在您的类MyClass 中声明类型为intstring 的数据成员,可以通过out 返回,因此您需要分配内存。

假设您在 MyClass 类中声明了数据成员 int var;,那么 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));
    }
};

【讨论】:

  • 这可以工作,但如果我有机会进入多个线程,它可能会爆炸。我想在我正在调用的类之外​​创建输出变量。
  • @aquawicket:那么在这种情况下,您可以简单地执行int out_int; void *out = (void*)&amp;out_int;GetNumber(void* input, void *output) { *output = what_ever_int_value_you_like;}
  • GetNumber(void* input, void* output){ int num = 69; *output = num; } *输出是非法间接,无论我分配什么。
  • out 在调用GetNumberGetNumber之前是否指向某些东西?
  • int finalout = 13579; void* out = (void*)finalout; MyFuncs::CallFunc("MyClass::GetNumber", NULL, out); 非法间接,即使 *output = NULL;在函数内部。
【解决方案2】:

解决方案
在不使用 static_cast 或额外的 boost 函数的情况下,我能够使用纯 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.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
}

【讨论】:

    猜你喜欢
    • 2014-05-30
    • 2019-09-27
    • 2012-05-06
    • 2011-04-01
    • 2011-06-17
    • 2021-07-22
    • 2014-05-13
    相关资源
    最近更新 更多