0

我正在尝试使我的应用程序的一部分可编写脚本。我有一个对象“GraphLogic”,其中包含一个关于“块”对象的指针表。我想在我的脚本中访问这个对象。

#include <QObject>
#include <QString>

class Block;

class GraphLogic: public QObject
{
    Q_OBJECT
public:
    explicit GraphLogic( int Heads, int Rows)
    virtual ~GraphLogic();
…
Q_INVOKABLE int getLines() const;
Q_INVOKABLE int getColumns() const;

Q_INVOKABLE Block* getBlock(int Col, int Row);
QString exportSeq(const QString& rScript);
…

QList< QList< Block*> > m_BlockTable;
};

实现(graphlogic.cpp):

#include "graphlogic.h"
#include "block.h"

#include <QJSEngine>
#include <QQmlEngine>

GraphLogic::GraphLogic(int Col, int Rows){
for(int ColIndex = 0; ColIndex < Col; ++ ColIndex)
{
   m_BlockTable.append(QList<Block*>());
   for(int Index = 0; Index < Rows; ++Index)
   {
       m_BlockTable[ColIndex].append(nullptr);
   }
}
}

GraphLogic::~GraphLogic()
{
for(int ColIndex = 0; ColIndex < m_BlockTable.size(); ++ ColIndex)
{
   for(int Index = 0; Index < m_BlockTable[0].size(); ++Index)
   {
       if(m_BlockTable[ColIndex][Index])
       {
           delete m_BlockTable[ColIndex][Index];
           m_BlockTable[ColIndex][Index] = nullptr;
       }
   }
}
}

int GraphLogic::getLines() const
{
return m_BlockTable[0].size();
}

int GraphLogic::getColumns() const
{
return m_BlockTable.size();
}

Block* GraphLogic::getBlock(int Col, int Row)
{
if(Col < 0 || Col >= m_BlockTable.size() || Row < 0 || Row >=       m_BlockTable[0].size())
{
    return nullptr;
}

 return m_BlockTable[Col][Row];
}

bool GraphLogic::addBlock(Block* pBlock, int Row, int Col)
{
if(Col < 0 || Col >= m_BlockTable.size() || Row < 0 || Row >=    m_BlockTable[0].size())
{
    return false;
}

 m_BlockTable[Col][Row] = pBlock;
}


QString GraphLogic::exportSeq(const QString& rScript)
{
QJSEngine engine;
qmlRegisterType<Block>();

//this ->Logic object
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);

QJSValue LogicValue = engine.newQObject(this);
engine.globalObject().setProperty("Logic", LogicValue);

QJSValue SeqStr = engine.evaluate(rScript);
QJSValue Res = SeqStr.call();
return Res.toString();
}

我也使Block::GetLabel()方法可编写脚本。这是类block.h:

#include <QObject>

class Block: public QObject
{
Q_OBJECT
public:

Block(const QString &rLabel);
virtual ~Block();

Q_INVOKABLE QString getLabel() const;
private:

QString m_Label;
};

和block.cpp:

#include "block.h"

Block::Block(const QString &rLabel)
    : m_Label(rLabel)
{

}

Block::~Block()
{

}

QString Block::getLabel() const
{
    return m_Label;
}

我可以使我的“GraphLogic”对象可用于脚本,它工作正常。当我尝试访问块对象时,我可以获得块标签,脚本到最后并正常退出。

Macro.qs(作为参数传递给GraphLogic::export):

(function logicToString()
{
    var Out;
    var i, j;
    for(i = 0; i < Logic.getColumns(); ++i)
    {
        for(j = 0; j < Logic.getLines(); ++j)
        {
            if(Logic.getBlock(i,j) != null)
            {
               // b is Block* !
               var b = Logic.getBlock(i,j);
               Out += b.getLabel();
            }
            Out += ";";
        }
        Out += "\n";
    }
return Out;
})

但是当我再次尝试访问Block对象时,它会崩溃。这是示例main.cpp

#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include "graphlogic.h"
#include "block.h"

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

GraphLogic Logic(3,3);
Block* pNewBlock = new Block("first");
Logic.addBlock(pNewBlock, 0,0);
pNewBlock = new Block("second");
Logic.addBlock(pNewBlock, 1,1);

QString JSFile("./Macro.qs");
QFile ScriptFile(JSFile);
if(ScriptFile.open(QIODevice::ReadOnly))
{
    QTextStream Stream(&ScriptFile);
    QString ExportScript = Stream.readAll();

    //output:
    //"first;0;0;\n0;second;0;\n0;0;0;\n"
    qDebug() << Logic.exportSeq(ExportScript);

}
ScriptFile.close();

Block* pBlock = Logic.getBlock(0,0);
if(pBlock)
{
    //crash SEG FAULT
    qDebug()<< pBlock->getLabel();
}
return a.exec();

}

可能是因为它们已经被 QJSEngine 销毁了?我说这是因为当我忘记明确声明GraphLogic对象的所有权为QQmlEngine::CppOwnership时,发生了同样的问题。

所以,我想我必须找到一种方法来防止 QJSEngine 破坏Block对象。与QQmlEngine::setObjectOwnership相同,但在 javascript 中,因为我无法访问脚本之外的当前块。关于如何实现这一目标的任何想法?谢谢,

4

0 回答 0