Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 5

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 ]