从脚本调用的C ++函数调用对象实例

时间:2012-10-14 19:07:50

标签: c++ qt qtscript

我有一个名为Jellyfish的班级使用单身设计模式:

jellyfish.h

#ifndef JELLYFISH_H
#define JELLYFISH_H

#include <QHash>
#include <QScriptEngine>

class QScriptValue;

class Jellyfish : public QObject
{

    public:

         static Jellyfish * getInstance();
         static Jellyfish * instance;

    private:

        Jellyfish();

};

#ifndef

jellyfish.cpp

Jellyfish * Jellyfish::instance = NULL;

Jellyfish * Jellyfish::getInstance()
{

    if ( !Jellyfish::instance )
    {
        Jellyfish::instance = new Jellyfish();
    }

    return Jellyfish::instance;

}

当我在main.cpp并进行测试时,我没有错误:

的main.cpp

#include <QApplication>

#include "jellyfish.h"

class Jellyfish;

int main( int argc, char *argv[] )
{

    QApplication app( argc, argv );

    Jellyfish *toto = Jellyfish::getInstance();
    Jellyfish *toto2 = Jellyfish::getInstance();
    Jellyfish *toto3 = Jellyfish::getInstance();

    return app.exec();

}

但我想在外部QScript文件中使用Jellyfish中的一些静态方法:

jellyfish.h

private:

    static QScriptValue set( QScriptContext *context, QScriptEngine *engine );
    QScriptEngine *script_engine;

jellyfish.cpp

Jellyfish::Jellyfish()
{

    script_engine = new QScriptEngine;

    /* ... */

    initScriptEngine();

}

void Jellyfish::initScriptEngine()
{

    QScriptValue object = script_engine->newQObject( this );

    object.setProperty( "set", script_engine->newFunction( set ) );

    script_engine->globalObject().setProperty( "jellyfish", object );

}

QScriptValue Jellyfish::set( QScriptContext *context, QScriptEngine *engine )
{

    // I have to load instance because I am in a static method.
    // But this is where the application loop endlessly.
    Jellyfish *jellyfish = Jellyfish::getInstance();
    return true;

}

最终解析的脚本:

jellyfish.set( "line_numbers",  true );

问题

当我运行应用程序时,getInstance()总是会创建一个新的Jellyfish实例。但真正的问题是在使用debug(qDebug() << "test";)的输出上,我可以看到应用程序循环Jellyfish::getInstance();,直到我得到sgmentation fault

有人可以帮助我理解这个吗?

1 个答案:

答案 0 :(得分:1)

这是因为你的Jellyfish构造函数递归地调用它自己!

在调试器中破解你的程序,你会看到这样的回溯:

   ...
   Jellyfish::Jellyfish()
   Jellyfish::getInstance()
   Jellyfish::set
   Jellyfish::initScriptEngine() 
   Jellyfish::Jellyfish()
   Jellyfish::getInstance()

问题是你的构造函数调用了Jellyfish::getInstance(),但是当构造对象时,Jellyfish::instance仍为NULL:

Jellyfish * Jellyfish::getInstance()
{

    if ( !Jellyfish::instance )
    {
        // this line
        // Jellyfish::instance = new Jellyfish();
        // is equivalent to
        Jellyfish * temp = new Jellyfish(); // *
        Jellyfish::instance = temp; // not NULL after construction
    }

    return Jellyfish::instance;

}

如果从构造函数中调用getInstance(),则它将始终导致无限递归(直到segfault)。唯一的解决方案是不是从构造函数调用Jellyfish :: initScriptEngine() - 而是显式:

   Jellyfish::getInstance()->initScriptEngine();