2

我正在尝试将函数指针(类型为QScriptEngine::FunctionSignature(= QScriptValue (QScriptContext *, QScriptEngine *)))传递给另一个函数。但是我需要传递的函数是一个类的成员函数。

我这样使用它:

class MyClass
{
    SomeVarType someVarINeedAccessTo;

    QScriptValue print(QScriptContext* context, QScriptEngine* engine)
    {
        ... someVarINeedAccessTo ...
    }

    void someFunction()
    {
        QScriptEngine engine;
        QScriptValue printFunction = engine.newFunction(print);
        engine.globalObject().setProperty("print", printFunction);
    }
};

在这个例子中,我得到了错误:

error: no matching function for call to QScriptEngine::newFunction(<unresolved overloaded function type>) note: candidates are: ...

如何将打印功能传递给 newFunction?

编辑:

我这样修复它:

class MyClass
{
    public:
         ...

         class TheEngine : public QScriptEngine
         {
             public:
                  MyClass* instance;
         };

         static QScriptValue print(QScriptContext *context, QScriptEngine *engine);

         void someFunction();

         ...
 };

 Myclass::someFunction()
 {
     TheEngine engine;

     ...

     QScriptVaue printFunction = engine.createFunction(print);
     engine.globalObject().setProperty("print", printFunction);

     ...
 }

 QScriptValue MyClass::print(QScriptContext* context, QScriptEngine* engine)
 {
      TheEngine* eng = dynamic_cast<TheEngine*>(engine);
      eng->instance->doSomething(...);
      return engine->undefinedValue();
 }
4

4 回答 4

1

这不起作用,因为函数不是方法,因此签名不同。与其他语言不同,在 C++ 中,方法不绑定到对象,因此它作为方法的签名,需要应用于对象。

您应该做的是包装一个具有良好签名的正确函数(或静态函数),并在作为参数传递的对象上调用您想要的方法。

MyClass : public QScriptEngine {
  static QScriptValue static_print(QScriptContext* context, QScriptEngine* engine)
  {
    MyClass *my_engine = dynamic_cast<MyClass>(engine)
    my_engine->print(context);
  }

// redefine print to take only one argument.

}

也许您希望将 your_class 作为上下文的属性而不是作为引擎传递,但这就是想法。您需要一个静态包装器到您的方法中,在参数中的某个位置应用您的函数。

于 2010-11-23T15:14:49.543 回答
0

尝试限定标识符:

QScriptValue printFunction =
    engine.newFunction(&MyClass::print);

编辑:

当我看到函数的声明时,您必须boost::bind按照其他建议使用:

QScriptValue printFunction =
    engine.newFunction(boost::bind(&MyClass::print, this, _1, _2));

boost::bind将要调用的方法和对象 ( this) 转换为可以在对象上调用该方法的对象。

于 2010-11-23T14:54:34.450 回答
0

仅传递成员函数引用可能会遇到的问题是成员函数需要一个对象实例来执行。如果是这样,请查看 Boost.bind,尤其是这部分。假设您希望 print() 方法适用于您MyClass类型的当前对象,您可能需要这样的东西:

class MyClass
{
    SomeVarType someVarINeedAccessTo;

    QScriptValue print(QScriptContext* context, QScriptEngine* engine)
    {
        ... someVarINeedAccessTo ...
    }

    void someFunction()
    {
        QScriptEngine engine;
        engine.globalObject().setProperty("print", 
           boost::bind(&MyClass::print, this, _1, _2));
    }
};

这可能会导致您稍微修改 setProperty()。

于 2010-11-23T15:08:50.843 回答
0

不幸的是,在 C++ 中没有办法在需要常规函数指针的地方传递成员函数。指向成员函数的指针不是函数指针,只能与对象指针一起使用。

您将不得不编写一个静态函数并从“其他地方”获取指向您的 MyClass 对象的指针:

  1. 可能有一种方法可以将指向您的对象的指针存储到将传递给您的函数的 QScriptEngine 或 QScriptContext 对象的某些“用户数据”或“上下文”字段中?阅读文档以了解 Qt 开发人员是否对您很好。

  2. 使用全局 std::map 将您的 MyClass 对象之一与每个 QScriptEngine 关联。

  3. 如果你关心性能,不关心可移植性,知道什么是调用约定,看看开源的 libffi 库(http://sourceware.org/libffi/),它允许你构造函数指针在运行时。对于您的普通 Qt 应用程序,这太过分了。

于 2010-11-23T15:19:05.597 回答