Pass member function pointer in C++

 ̄綄美尐妖づ 提交于 2019-12-10 11:24:11

问题


I am trying to pass a function pointer (of type QScriptEngine::FunctionSignature (= QScriptValue (QScriptContext *, QScriptEngine *))) to an other function. But the function I need to pass is a member function of a class.

I use it like this:

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);
    }
};

With this example I get the error:

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

How can I pass the print function to newFunction?

EDIT:

I fixed it like this:

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();
 }

回答1:


That doesn't work because a function is not a method and so the signature are different. As opposed to other language, in C++ a method is not bound to an object, so it as the signature of a method and need to be applied on a object.

What you should do is wrap a proper function which (or a static one) with the good signature and call the method you want on the object passed as argumment.

like

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.

}

Maybe you would like instead to pass your_class as an attribute of the context rather than being the engine, but that's the idea. You need a static wrapper to your method with somewhere in the argument the object to apply your function on it.




回答2:


The problem you may have with just passing the member function reference is that the member function needs an object instance to execute against. If so, have a look at Boost.bind, in particular, this part. Assuming that you want the print() method to the current object of your MyClass type, you might want something like this:

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));
    }
};

This will probably cause you to rework setProperty() a little.




回答3:


Unfortunately, there is no way in C++ to pass a member function where a regular function pointer is expected. A pointer to a member function is NOT a function pointer, and can only be used in conjunction with an object pointer.

You will have to write a static function and get a pointer to your MyClass object from "somewhere else":

  1. There might be a way to store a pointer to your object into some "user data" or "context" field of the QScriptEngine or QScriptContext objects that will get passed to your function? Read the documentation to find out if the Qt developers were nice to you.

  2. Use a global std::map to associate one of your MyClass objects with each QScriptEngine.

  3. If you care about performance, don't care about portability, know what a calling convention is, have a look at the open-source libffi library (http://sourceware.org/libffi/), which allows you to construct function pointers at runtime. For your average Qt application, this is way overkill.




回答4:


Try qualifying the identifier:

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

EDIT:

As I see the declaration of the function, you have to use boost::bind as other suggested:

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

boost::bind converts the method and the object to be called (this) into an object that can call that method on the object.



来源:https://stackoverflow.com/questions/4257239/pass-member-function-pointer-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!