QJSEngine вызывает сбой при выходе при обращении к указателю на объект C ++ - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь сделать часть своего приложения доступной для сценариев.У меня есть объект «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 class 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, потому что у меня нет доступа к текущему блоку вне скрипта.Есть идеи, как мне этого добиться?Спасибо,

...