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();
}
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.
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.
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":
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.
Use a global std::map to associate one of your MyClass objects with each QScriptEngine.
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.
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