Qt-interest Archive, June 2007
QtScript: throwing an Error with traceback stack
Message 1 in thread
From a c++ function that is called from a script I would like to throw
an Error including the traceback stack information, somethin alike:
void MyScriptableClass::scriptableFunction()
{
// some function code here
if (someerror) {
context->throwError(
"Some error happened",
__FILE__, __LINE__, __FUNCTION__);
return;
}
// further function code here
}
Of cause such a variant of throwError does not exist, the code above
is just to show what I would like to do. Does anybody have an idea how
this could be done?
--
[ signature omitted ]
Message 2 in thread
Qt list all toolbars in the toolbar's context menu by default. I'd like
to control what's shown and hidden in that menu. What's the best way to
do it?
Thanks,
Tamara Nguyen
Software Engineer
PDF Solutions, Inc.
(408) 283 5655
CONFIDENTIALITY NOTICE: This e-mail is meant only for the intended
recipient. It contains information that may be confidential and
privileged. Unless you are the intended recipient (or authorized to
receive for the intended recipient), you are prohibited from reviewing,
using, copying, forwarding, retaining or disclosing to anyone this
e-mail or any information in the e-mail (including any attachment). If
you have received this e-mail in error, please send a reply e-mail only
to the sender (tamara.nguyen@xxxxxxx <mailto:tamara.nguyen@xxxxxxx>) and
delete this message from your system. My apologies for any
inconvenience, and thank you in advance for your cooperation.
>
>
Message 3 in thread
On 6/22/07, Seneca <acenes@xxxxxxx> wrote:
> From a c++ function that is called from a script I would like to throw
> an Error including the traceback stack information, somethin alike:
>
> void MyScriptableClass::scriptableFunction()
> {
> // some function code here
> if (someerror) {
> context->throwError(
> "Some error happened",
> __FILE__, __LINE__, __FUNCTION__);
> return;
> }
> // further function code here
> }
>
> Of cause such a variant of throwError does not exist, the code above
> is just to show what I would like to do. Does anybody have an idea how
> this could be done?
Sure, use throwValue() instead. So, you create a new ScriptValue that
will be your exception object, and add the appropriate properties
(file, line etc.) then call throwValue to send the exception.
Cheers
Rich.
--
[ signature omitted ]
Message 4 in thread
RM> Sure, use throwValue() instead. So, you create a new ScriptValue that
RM> will be your exception object, and add the appropriate properties
RM> (file, line etc.) then call throwValue to send the exception.
Maybe I'm overlooking something obvious, but how exaclty can I create
an object of type Error in c++? QScriptEngine::newObject() creates
only a basic object derived from Object, instead of one derived from Error.
What might come close is something as:
// create location object for the stack
QScriptValue location = engine->newObject();
location.setProperty("fileName", toScriptValue(__FILE__));
location.setProperty("lineNumber", toScriptValue(__LINE__));
location.setProperty("functionName", toScriptValue(__FUNCTION__));
// create stack array with one location
QScriptValue stack = engine->newArray();
stack.setProperty(0, location);
// create Error object and set properties
QScriptObject err = context->throwError("the message"); // Arghh...
err.setProperty("fileName", toScriptValue(__FILE__));
err.setProperty("lineNumber", toScriptValue(__LINE__));
err.setProperty("stack", stack);
// throw modifier Error object
context->throwValue(err);
I dont know if using both, throwError to create a Error object and then
throwValue to throw the modified Error object has any side effects.
Also inspecting the location objects of a "real" Error's stack, there
is another (undocumented) property named "frame". Do I need to create
such also?
--
[ signature omitted ]
Message 5 in thread
On 6/22/07, Seneca <acenes@xxxxxxx> wrote:
> RM> Sure, use throwValue() instead. So, you create a new ScriptValue that
> RM> will be your exception object, and add the appropriate properties
> RM> (file, line etc.) then call throwValue to send the exception.
>
> Maybe I'm overlooking something obvious, but how exaclty can I create
> an object of type Error in c++? QScriptEngine::newObject() creates
> only a basic object derived from Object, instead of one derived from Error.
Yeah, I did request this object be made available during the
pre-releases but I guess it never got done. It is possible however to
throw any object, there's no requirement that you only throw 'Error'.
That said, I guess you could do something like:
engine->evalute( "myerror = new Error()" );
when your program starts then access the error object later with:
err = engine->globalObject().property("myerror");
err.setProperty("fileName", toScriptValue(__FILE__));
err.setProperty("lineNumber", toScriptValue(__LINE__));
context->throwValue(err);
the stack etc. should get filled in by the engine as the exception
propagates up the scopes.
Cheers
Rich.
--
[ signature omitted ]
Message 6 in thread
I now got it working - but must say its a bit cumbersome, so a nice API
from trolltech would be welcome. Anyway below is the core of my
current solution:
/**
* Throw a script error of the exeption.
* This is useful in c++ code that was called from a script,
* for example in classes derived from QScriptable.
* \return QScriptValue representation of the exeption as Error object.
* \code
* void MyScriptableClass::myScriptableFunction()
* {
* try {
* // Some code here that might throw a MyException
* }
* catch (const MyException& exc) {
* if (!context) throw; // function was called from c++ code
* return exc.throwScriptError(context);
* }
* }
* \endcode
*/
QScriptValue MyException::throwScriptError(QScriptContext* context) const
{
MY_PRV(const MyException)
QScriptEngine* engine(context->engine());
QScriptValue error(engine->evaluate("return Error();"));
error.setProperty("message", engine->toScriptValue(prv->message));
int cnt(prv->stack.size());
if (cnt > 0) {
// make room for c++ location stack
QScriptValue stack(error.property("stack"));
int sl(stack.property("length").toInt32());
for (int s = sl-1; s >= 0; s--)
stack.setProperty(s+cnt, stack.property(s));
// fill in c++ stack
for (int s = 0; s < cnt; s++) {
QScriptValue location(engine->newObject());
location.setProperty("fileName", engine->toScriptValue(prv->stack[s].file));
location.setProperty("lineNumber", engine->toScriptValue(prv->stack[s].line));
location.setProperty("functionName", engine->toScriptValue(prv->stack[s].function));
stack.setProperty(s, location);
} // for
// set error properties
error.setProperty("fileName", engine->toScriptValue(prv->stack[0].file));
error.setProperty("lineNumber", engine->toScriptValue(prv->stack[0].line));
error.setProperty("stack", stack);
} // if
return context->throwValue(error);
} // throwScriptError
Hints:
prv is a pointer to the private members of MyException.
prv->message is a QScript with the c++ exception message.
prv->stack is a QList of one or more c++ locations.
--
[ signature omitted ]
Message 7 in thread
Seneca wrote:
> I now got it working - but must say its a bit cumbersome, so a nice API
> from trolltech would be welcome. Anyway below is the core of my
> current solution:
>
[...]
Hi Seneca,
I agree that this can be improved; the availability of debugging-related
facilities and APIs is one of the main things we're addressing for Qt
4.4. Thanks for sharing your experiences.
Regards,
Kent
--
[ signature omitted ]