问题描述
在我的工作项目中,我遇到了一种特别奇怪的行为。在运行时,当调用 QMetaObject::invokeMethod 时,我得到一个打印,表明程序正在尝试从 QObject 中查找指定的方法,而不是我给它的指针指向的实际类。更奇怪的是,我制作了一个模型,在我看来,它的功能与正确的代码大致相同,不同之处在于模型实际上执行了预期的操作。我找不到两者之间有意义的差异,也找不到我的代码无法正常运行的原因。
请原谅所示代码中的一些不良做法。由于与此问题无关的原因,我被迫编辑部分代码,主要是类和库的名称,并且在保持实际代码中的质量方面做得并不好。这对实际功能没有影响,只会影响可读性。
我会根据要求提供模型的代码,但这段代码实际上是我遇到的问题,所以我觉得添加只会导致不必要的膨胀。
编辑
我是个笨蛋,忘了包含错误信息。请注意,这也与代码库进行了类似的编辑(即,类名称和一些函数名称已更改)
QMetaObject::invokeMethod: No such method QObject::simpleRx(QString,int,client*)
编辑 #2 好的,问题的根源在于 Host 中缺少 Q_OBJECT 宏。现在我收到一个“QMetaMethod::invoke: Unable to handle unregistered datatype ‘int&’”错误,我接下来会研究。
main.cpp
#include "maincontroller.h"
int main(int argc,char *argv[])
{
QCoreApplication a(argc,argv);
MainController mc(argc,argv);
return a.exec();
}
主控制器.h
class MainController : public QObject
{
Q_OBJECT
private:
//attributes
client* comm;
host* host;
bool allOk;
QStringList argList;
int parseArguments(QStringList &arguments,int argc,char *argv[]);
public:
//methods
explicit MainController(int argc,char *argv[],QObject *parent = nullptr);
};
#endif // MAINCONTROLLER_H
主控制器.cpp
#include "client.h"
#include "host.h"
#include <QCoreApplication>
MainController::MainController(int argc,QObject *parent) : QObject(parent)
{
if(true)
{
host=new host();
comm=new client(host,"main",this,0);
//connect(comm,&client::killSignal,&MainController::quit);
}
else
{
exit(EXIT_FAILURE);
}
}
客户端.h
#define client_H
#include <QObject>
class QUuid;
class host;
class client : public QObject
{
Q_OBJECT
public:
explicit client(host* givenHost,QString givenId,QObject* giveNowner,int givenPriority,QObject *parent=nullptr);
signals:
void killSignal();
public slots:
private:
//attributes
//pointer to the instance that is using this instance of client
QObject* owner;
QString simpleId; //placeholder attribute until id mess is sorted
host* host;
QHash<QString,const char*>* handlers;
//methods
public:
//attributes
//methods
explicit client(host* givenHost,QObject *parent=nullptr);
int simpleTx(QString msg,QString msgName,QString simpleTarget,client* clientPtr=nullptr);
int registerMe(QString threadName);
};
#endif // client_H
client.cpp
#include "host.h"
#include "globals.h"
#include<QUuid>
#include <QHash>
#include<QJsonObject>
#include<QJsonDocument>
#include <QMetaObject>
#include<QDebug>
client::client(host* givenHost,QObject *parent) : QObject(parent),host(givenHost),handlers(new QHash<QString,const char*>),owner(giveNowner),simpleId(givenId),priority(givenPriority)
{
id = new QUuid();
id->createUuid();
registerMe(givenId);
}
//registers this instance of client to host and sets simpleId to threadName
int client::registerMe(QString threadName)
{
QJsonObject payload;
payload.insert(SIMPLEID,threadName);
payload.insert(PRIORITY,priority);
payload.insert(ID,id->toString(QUuid::StringFormat::WithoutBraces));
simpleId = threadName;
simpleTx(JSONtoStr(payload),IPCREGISTRATIONHEADER,HOST,this);
return ALLCLEAR;
}
int client::simpleTx(QString msg,QString SimpleTarget,client* clientPtr)
{
int transmitReturnValue = 420;
QJsonObject payload = StrToJSON(msg);
QString fullMsg = JSONtoStr(JSONify(simpleId,SimpleTarget,msgName,payload));
if(QMetaObject::invokeMethod(host,"simpleRx",Qt::QueuedConnection,Q_ARG(QString,fullMsg),Q_ARG(int,transmitReturnValue),Q_ARG(client*,nullptr)))
{
return ALLCLEAR;
}
else
{
return INVOKEERROR;
}
}
int client::registerHandler(QString msgName,const char* method)
{
handlers->insert(msgName,method);
return ALLCLEAR;
}
int client::getPriority()
{
return priority;
}
QJsonObject client::JSONify(QString src,QString dst,QJsonObject payload)
{
QJsonObject header;
QJsonObject msg;
header.insert(SRC,src);
header.insert(DST,dst);
header.insert(MSGNAME,msgName);
msg.insert(HEADER,header);
msg.insert(PAYLOAD,payload);
return msg;
}
QString client::JSONtoStr(QJsonObject json)
{
QJsonDocument doc(json);
QString msgString(doc.toJson(QJsonDocument::Compact));
return msgString;
}
QJsonObject client::StrToJSON(QString jsonString)
{
QJsonObject obj;
QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8());
// check validity of the document
if(!doc.isNull())
{
if(doc.isObject())
{
obj = doc.object();
}
else
{
qDebug() << "Document is not an object";
}
}
else
{
qDebug() << "Invalid JSON...\n" << jsonString;
}
return obj;
}
host.h
#define host_H
#include <QObject>
class client;
class host : public QObject
{
signals:
public slots:
private:
//attributes
QHash<QUuid*,client*>* registeredClients;
QHash<QString,client*>* simpleRegisteredClients;
QList<int> priorities;
//methods
int rx(QString jsonString,client* clientPtr);
Q_INVOKABLE void simpleRx(QString jsonString,int &transmitreturnvalue,client* clientPtr=nullptr);
QJsonObject StrToJSON(QString jsonString);
public:
//attributes
//methods
explicit host(QObject *parent = nullptr);
};
#endif // host_H
host.cpp
#include "clent.h"
#include "globals.h"
#include<QJsonDocument>
#include<QJsonObject>
#include<QDebug>
host::host(QObject *parent) : QObject(parent)
{
}
void host::simpleRx(QString jsonString,int &transmitReturnValue,clent* clientPtr)
{
QString msgName = StrToJSON(jsonString).value(HEADER).toObject().value(MSGNAME).toString();
int rxret = 1;
if(msgName==REGISTRATIONHEADER)
{
QString clientName = StrToJSON(jsonString).value(PAYLOAD).toObject().value(SIMPLEID).toString();
simpleRegisteredClients->insert(clientName,clientPtr);
if(clientPtr->getPriority()!=0)
{
priorities.push_back(clientPtr->getPriority());
}
transmitReturnValue = ALLCLEAR;
}
else if(msgName==ACCEPTDEATH)
{
QString simpleName = StrToJSON(jsonString).value(PAYLOAD).toObject().value(SIMPLEID).toString();
simpleRegisteredClients->remove(simpleName);
}
else if(msgName==KILLMESSAGE && StrToJSON(jsonString).value(HEADER).toObject().value(DST).toString()==ALL)
{
std::sort(priorities.begin(),priorities.end());
QHash<QString,clent*>::iterator i;
while(!priorities.empty())
{
int currentPriority = priorities.takeLast();
for (i = simpleRegisteredClients->begin(); i != simpleRegisteredClients->end(); ++i)
{
if(i.value()->getPriority()==currentPriority)
{
QMetaObject::invokeMethod(i.value(),"rx",Qt::ConnectionType::QueuedConnection,Q_RETURN_ARG(int,rxret),jsonString));
}
}
}
QJsonObject finalMsg;
QJsonObject payload;
QJsonObject header;
QString finalJsonString;
header.insert(SRC,HOST);
header.insert(MSGNAME,FINALMESSAGE);
finalMsg.insert(HEADER,header);
finalMsg.insert(PAYLOAD,payload);
for (i = simpleRegisteredClients->begin(); i != simpleRegisteredClients->end(); ++i)
{
if(i.value()->getPriority()==0)
{
QMetaObject::invokeMethod(i.value(),finalJsonString));
}
}
}
else
{
QString clientName = StrToJSON(jsonString).value(HEADER).toObject().value(DST).toString();
bool invokeSuccesful=false;
invokeSuccesful = QMetaObject::invokeMethod(simpleRegisteredClients->value(clientName),jsonString));
if(!invokeSuccesful)
{
qDebug() << "Invoke was not succesful";
transmitReturnValue = INVOKEERROR;
}
}
transmitReturnValue = ALLCLEAR;
}
QJsonObject host::StrToJSON(QString jsonString)
{
QJsonObject obj;
QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8());
// check validity of the document
if(!doc.isNull())
{
if(doc.isObject())
{
obj = doc.object();
}
else
{
qDebug() << "Document is not an object";
}
}
else
{
qDebug() << "Invalid JSON...\n" << jsonString;
}
return obj;
}
CMakeLists.txt
project(myProject LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core required)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network required)
set(srcPath ${CMAKE_CURRENT_LIST_DIR}/sources)
set(hdrPath ${CMAKE_CURRENT_LIST_DIR}/headers)
set(extLib ${CMAKE_CURRENT_SOURCE_DIR}/../../externals/path_to/so_file)
set(libIncludes ${CMAKE_CURRENT_SOURCE_DIR}/../../externals/path_to/library/source/)
set(fileList
${srcPath}/main.cpp
${srcPath}/client.cpp
${srcPath}/host.cpp
${srcPath}/maincontroller.cpp
${hdrPath}/maincontroller.h
${hdrPath}/globals.h
${hdrPath}/client.h
${hdrPath}/host.h
)
add_executable(myProject
${fileList}
)
set_target_properties(myProject PROPERTIES
AUTOMOC ON
CXX_STANDARD 17
CXX_STANDARD_required ON
VERSION 0.9.0
EXPORT_NAME "myProject"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/build/archive"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/build/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/build/run"
)
target_include_directories(myProject PRIVATE headers/)
target_include_directories(myProject PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/headers ${libIncludes})
target_link_libraries(myProject PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network ${extLib})
我在 Ubuntu 20.04 上运行 Qt 6.1.0
请询问您需要的任何更多详细信息,如果可以,我会提供。
非常感谢您的帮助。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)