我正在尝试使我的应用程序的一部分可编写脚本。我有一个对象“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 中,因为我无法访问脚本之外的当前块。关于如何实现这一目标的任何想法?谢谢,