创建在运行时创建的函数的函数指针

时间:2010-01-08 03:08:14

标签: c++ lambda

我想做点什么:

for(int i=0;i<10;i++)
    addresses[i] = & function(){ callSomeFunction(i) };

基本上,拥有一系列具有与数字列表相关的行为的函数地址。

如果可以使用像Boost.Lambda这样的外部类,那么

编辑:经过一番讨论,我得出的结论是我不够明确。请阅读Creating function pointers to functions created at runtime


我最终真正想做的是:

class X
{
    void action();
}

X* objects;

for(int i=0;i<0xFFFF;i++)
    addresses[i] = & function(){ objects[i]->action() };


void someFunctionUnknownAtCompileTime()
{

}

void anotherFunctionUnknowAtCompileTime()
{

}

使用程序集修补someFunctionUnknownAtCompileTime()以跳转到地址处的函数[0]

使用程序集修补anotherFunctionUnknownAtCompileTime()以跳转到地址处的函数[1]

是的,我不认为你的方法会起作用,因为它们不是真正的功能,但我不能完全解释我想要做什么。

7 个答案:

答案 0 :(得分:3)

如果我理解正确,你试图用运行时生成的机器代码填充一个缓冲区,并获得一个指向该代码的函数指针,以便你可以调用它。

这是可能的,但具有挑战性。您可以使用reinterpret_cast<>将数据指针转换为函数指针,但是您需要确保为缓冲区分配的内存被操作系统标记为可执行。这将涉及系统调用(在Windows iirc上LocalAlloc(),在Unix上无法记住)而不是“普通的”malloc / new调用。

假设你有一个可执行的内存块,你必须确保你的机器代码遵守你创建的函数指针所指示的调用约定。这意味着在函数开头等推送/弹出适当的寄存器

但是,一旦你完成了,你应该能够像使用任何其他功能一样使用你的函数指针。

可能值得一看开源JVM(或Mono)以了解它们是如何做到的。这是JIT编译的精髓。

答案 1 :(得分:2)

以下是我刚刚攻击的一个例子:

int func1( int op )
{
   printf( "func1 %d\n", op );
   return 0;
}
int func2( int op )
{
   printf( "func2 %d\n", op );
   return 0;
}

typedef int (*fp)(int);


int main( int argc, char* argv[] )
{
    fp funcs[2] = { func1, func2 };
    int i;

    for ( i = 0; i < 2; i++ )
        {
        (*funcs[i])(i);
        }

}

答案 2 :(得分:1)

最简单的方法应该是创建一堆boost::function个对象:

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

std::vector< boost::function<void ()> > functors;
for (int i=0; i<10; i++)
   functors.push_back(boost::bind(callSomeFunction, i));

// call one of them:
functors[3]();

请注意,向量的元素不是“实际函数”,而是具有重载operator()的对象。通常这不应该是一个缺点,实际上比实际函数指针更容易处理。

答案 3 :(得分:0)

您可以通过事先在全局范围内通过某些任意名称定义这些函数来实现。

答案 4 :(得分:0)

这基本上就是上面所说的,但修改代码看起来像这样:

std::vector<int (*) (int)> addresses;
for(int i=0;i<10;i++) {
     addresses[i] = &myFunction;  
}

当你说在运行时创建的函数时,我的意思并不是很清楚...我不认为你可以在运行时创建一个函数,但你可以指定将哪些函数指针放入你的数组中/矢量在运行时。请记住,使用此方法,所有函数都需要具有相同的签名(相同的返回类型和参数)。

答案 5 :(得分:0)

如果没有this指针,则无法自行调用成员函数。类的所有实例都将函数存储在内存中的一个位置。当您调用p->Function()时,p的值存储在某处(无法记住它是一个寄存器还是堆栈),并且该值用作基本偏移量来计算成员变量的位置。

因此,如果要调用函数指针,则必须存储函数指针和指向对象的指针。一般的形式是这样的:

class MyClass {
  void DoStuf();
};

//on the left hand side is a declaration of a member function in the class MyClass taking no parameters and returning void.
//on the right hand side we initialize the function pointer to DoStuff
void (MyClass::*pVoid)() = &MyClass::DoStuff;

MyClass* pMyClass = new MyClass();
//Here we have a pointer to MyClass and we call a function pointed to by pVoid.
pMyClass->pVoid();

答案 6 :(得分:0)

正如我理解这个问题,你正试图在运行时创建函数(正如我们在Ruby中所做的那样)。如果这是意图,我担心在C ++这样的编译语言中是不可能的。 注意:如果我对问题的理解不正确,请不要downvote:)