PDA

View Full Version : QTScript - getting the name of a QScriptValue



android_
27th October 2009, 19:46
Hello,
i'm stuck at this for quite some time so i'll explain the situation to you in hope for help:

i have a script console where one can insert custom scripts based on qtscript,
there is a simulation which is accessed by a command

mysimulation = getsimulation("....")

a simulation is a class.
now when using specific commands on that simulation it normally works like this:

simulation_name = mysimulation.getname()

which calls the corresponding function and so on. the functions like getname() return of course QScriptValues to work with further. i'm currently scripting a function which needs to know the variable it's executed with.
in my example it would have to know that the name of the variable was "mysimulation".

my current way of doing that is: mynewfunction("mysimulation") but that is of course no good way for solving the problem. is there a way to get the name of the qscriptvalue/qobject (which it is also?) when its accessed?

i hope you can understand what i'm talking about :) thanks

JohannesMunk
27th October 2009, 23:20
Hi there!

What functions are native and which are scripted in your design? And is that choice right?

Usually you would implement the getname as a public slot (or better a q_property name) of your simulation-class which returns a QString. (The conversion between QString and QScriptValue is done automatically behind the scenes, when you call the function.).

Your class needs to be derived from QObject, needs the Q_OBJECT macro and you need to register the classtype with qScriptRegisterMetaType implementing the toScriptValue and FromScriptValue Functions.

Your native getname implementation in the SimulationClass can directly access the objects properties as usual..



class Simulation : public QObject
{ Q_OBJECT
Q_PROPERTY(QString name READ GetName)
public slots:
QString toString() {return QString("SimObject: %1").arg(GetName());}
public:
Simulation(QString pname) {_name = pname;}
QString GetName() {return _name;}
private:
QString _name;
};
Q_DECLARE_METATYPE(Simulation*)

QScriptValue SimulationToScriptValue(QScriptEngine *engine, Simulation* const &in)
{
return engine->newQObject(in,QScriptEngine::QtOwnership);
}
void SimulationFromScriptValue(const QScriptValue &object, Simulation* &out)
{
out = qobject_cast<Simulation*>(object.toQObject());
}

qScriptRegisterMetaType<Simulation*>(scripting, SimulationToScriptValue,SimulationFromScriptValue) ;



Your native getsimulation function (a function object of your global scripting object?) returns a pointer to an instance of your SimulationClass. Right?

If however you are trying to implement something which returns a QScriptValue or needs QScriptValueLists as parameters, let me know. But I doubt, that you need it. If you do, the thing you are probably looking for is the "this" object of the script context.

android_
28th October 2009, 12:24
thanks for the useful post,

well i was not interested in a specific getName() function, this was only an example to demonstrate how the code works.
i'm not interested in specific properties of the qobjects (like the simulation), i have to know the names of the objects/scriptvalues which the parser is creating at runtime. like in the example
mysimulation = getSimulation("")
so mysimulation is a qobject consisting of various data

success = mysimulation.isOpen()
a qscriptvalue (actually a bool) which can be used with the name "success"

mysimulation.newFunction()
the "newFunction()" in this case would have to know that it is called with the prefix "mysimulation", not the object but only the string of its dynamically generated name.

or did you understand what i mean and i didn't?
the simulation class is not a child of QObject, the getSimulation function converts the information in the simulation class to a QObject.

JohannesMunk
28th October 2009, 12:42
Ouch. No, I didn't get you. But now that I do, I can't think of a way to achieve this. If you were to implement your function like below you can access the very ScriptValue it was called from. But I don't know of a way to get the variable name. Sorry! QScriptValue doesn't feature a name property or something like that.

What I still don't get is your motivation to get the variable name. What do you want to do with it? You want to generate other scripts/code which access that variable? Well you can do that by accessing its QScriptValue passed as argument or as the this object like so:

That's the QScriptEngine::FunctionSignature.


QScriptValue CDBGetActionScript(QScriptContext *ctx, QScriptEngine *eng)
{
CDB* cdb = eng->fromScriptValue<CDB*>(ctx->thisObject());
return cdb->actionscript;
}




So here with the context's thisObject you can access the QScriptValue from which the function was called.



You need to register that function to each ScriptValue of that type.. upon its creation / conversion.


QScriptValue CDBToScriptValue(QScriptEngine *engine, CDB* const &in)
{
QScriptValue sv = engine->newQObject(in,QScriptEngine::QtOwnership);
sv.setProperty("Action",engine->newFunction(CDBGetActionScript),QScriptValue::Prop ertyGetter);
return sv;
}
void CDBFromScriptValue(const QScriptValue &object, CDB* &out)
{
out = qobject_cast<CDB*>(object.toQObject());
}

As an alternative you could create a prototype for the type. And add the function to it only once.

Right direction?

Johannes

android_
28th October 2009, 13:28
the purpose for that is a modified include function which already exists. i have a specific script which is used so often that it should be available in an own function.
when using the script you specify the simulation manually with a command like in my example. the idea is to use the runtime name of the simulation and insert it into the script automatically, so that the code can be parsed with the correct simulation.
there is of course a way of using the functions which would be called via the script directly in that function, but this method has other disadvantages.

thanks again for your time!

JohannesMunk
28th October 2009, 13:47
Hi there. So as I suspected you have one script which calls another dynamically created one. In the process of creating that other script you insert the name of the (global!) variable which is to be worked upon. Now you want this nameinsertion to work without explicitely passing the name to insert!

I think what you want to achieve is exactly why arguments to functions have been introduced. That you can call the same function with different values (or pointer to objects to be worked upon).

Your dynamic creation has one other major flaw: speed. Each time the simulation is started for a different simulationobject you need to reevaluate the generated simulationscript. If you were to use an argument you could just call the function directly.

Are you perhaps using the name of the object in your simulation script to switch between different cases? In that case I suggest an OOP approach. Just put every specialization into a class-member function and construct a proper inheritance-tree.

Now that we have nailed your question, maybe somebody else has a solution? Even so I would strongly recommend not using it in terms of code serviceability :->

Johannes

android_
28th October 2009, 14:12
it does already work with arguments, but the nature of the code would result in a function call like mysimulation.newfunction("mysimulation"), where the simulation is used as the argument.

anyway, i'm choosing the more complicated but resource friendly way of rebuilding the code, which the qtscript engine would have generated with the custom script, myself.

JohannesMunk
28th October 2009, 14:24
I was not talking of giving the object's name as argument to the script generator function.

What I meant was: forget about the script generator and just pass the simulationobject as parameter:

fixedsimulationfunc(mysimulation);

or better as it is more oop like:

mysimulation.run();

Here you use the this object to access mysimulation..

ScriptCode:


function run()
{
++this.time;
}

function()
{
// Initialize the run script.. maybe differently for different simulation objects?
simulation.run = run;
...
simulation.run();
}


Maybe I did still not catch why you want to do this.. Maybe you are forced to use the structure as it is.

Best of luck to you!

Johannes