Qt 动态加载动态库, QMetaObject元对象加载
由于通过pro文件加载第三方库导致程序崩溃(第三方库可能存在可能不存在,新旧版本在不同路径)
而通过自己构建空库在安装时会导致覆盖可能存在的第三方库
所以修改采用了QLibrary进行动态加载;
直接上代码#include "YHPostFaceLiving.h"
#include "../YHPostFaceLivingThird/YHPostFaceLivingThird.h" #include <QCoreApplication> #include <QDir> #include "stable.h" #include <QLibrary> #include <QProcess> extern "C" Q_DECL_EXPORT DeviceInterface *createDC(QString param) { Q_UNUSED(param); return new YHPostFaceLiving(); } class YHPostFaceLiving::PrivateData{ public: }; YHPostFaceLiving::YHPostFaceLiving() { #ifdef Q_OS_WIN interFace = NULL; #else interFace = loadDevice("param", "libYHPostFaceLivingThird.so");//动态加载 #endif QProcess *press = new QProcess; press->start("ls /lib64/libtesofacecv-living.so");//new sdk path press->waitForFinished(); QByteArray output = press->readAllStandardOutput(); QString x = output; if(interFace && (x != "")){ faceliving = static_cast<YHPostFaceLivingThird *>(interFace);//DeviceInterface是基类 //QObject *de = dynamic_cast<DeviceInterface*>(interFace); if (faceliving) { connect(faceliving, SIGNAL(error(int)), this, SLOT(get_error(int))); connect(faceliving, SIGNAL(remoteParam(QString)), this, SLOT(get_remoteParam(QString))); connect(faceliving, SIGNAL(imageCompResult(QString)), this, SLOT(get_imageCompResult(QString))); connect(faceliving, SIGNAL(programResult(QString,QString)), this, SLOT(get_programResult(QString,QString))); connect(faceliving, SIGNAL(programFail(QString,QString)), this, SLOT(get_programFail(QString,QString))); connect(faceliving, SIGNAL(getImageData(QString)), this, SLOT(get_getImageData(QString))); connect(faceliving, SIGNAL(openComplete()), this, SLOT(get_openComplete())); connect(faceliving, SIGNAL(closeComplete()), this, SLOT(get_closeComplete())); connect(faceliving, SIGNAL(resetComplete()), this, SLOT(get_resetComplete())); //下一次SDK更新确定版本号,通过版本号加载新旧SDK //QString version = getTesoVersion(); //if(version != "3.2.1") // faceliving = NULL; //LOGEVENT_INFO(QString("tesoface version :%1").arg(version)); } } else { interFace = NULL; faceliving = NULL; } } YHPostFaceLiving::~YHPostFaceLiving() { if (libLoader) { libLoader->unload(); delete libLoader; } libLoader = NULL; if (interFace) delete interFace; interFace = NULL; if (faceliving) delete faceliving; faceliving = NULL; } DeviceInterface* YHPostFaceLiving::loadDevice(QString param, QString libname) { typedef DeviceInterface* (*createDC)(QString); libLoader = new QLibrary(); QString path = QCoreApplication::applicationDirPath() + QDir::separator() + QString("devices") + QDir::separator() + libname; libLoader->setFileName(path); LOGEVENT_INFO("path:" + path); if (!libLoader->load()) { LOGEVENT_INFO("err:" + libLoader->errorString()); LOGEVENT_ERR(QString("third load lib false")); return NULL; } if (libLoader->isLoaded()) { createDC fun = (createDC)libLoader->resolve("createDC"); if (fun) { return fun(param); } else { LOGEVENT_ERR(QString("createDC fun is NUll")); return NULL; } } return NULL; } QVariant YHPostFaceLiving::executeFunc(QString func, QMap<QString, QString> &funcParams) { QVariant ret; bool bRes = false; const QMetaObject* mo = faceliving->metaObject(); if (mo) { QMetaMethod m = mo->method(mo->indexOfMethod(func.toLocal8Bit().data())); QList<QByteArray> parameterNames = m.parameterNames(); QList<QByteArray> parameterTypes = m.parameterTypes(); QVariant val[10] = {QVariant()}; for (int i = 0; i < parameterNames.size(); i++) { QString parame = parameterNames[i]; if (funcParams.contains(parame)) { QString value = funcParams.value(parame); QString type = parameterTypes[i]; //类型转换函数。其实可以只用另外一个executeFunc 参数通过QVariant(param)进行转换进去 val[i] = DeviceInterface::getParamVale(value, type.toLocal8Bit().data()); } else { LOGEVENT_ERR(QString("can't not find the parameter name[%1] in fun[%2], maybe you change the function").arg(parame).arg(func)); } } bRes = executeFunc(func, ret, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9]); } return ret; } bool YHPostFaceLiving::executeFunc(QString func, QVariant &ret, QVariant val0, QVariant val1, QVariant val2, QVariant val3, QVariant val4, QVariant val5, QVariant val6, QVariant val7, QVariant val8, QVariant val9) { bool bRes = false; const QMetaObject* mo = faceliving->metaObject(); int nIndex = mo->indexOfMethod(func.toLocal8Bit().data()); if (-1 != nIndex) { QMetaMethod m = mo->method(nIndex); QList<QByteArray> parameterTypes = m.parameterTypes(); QGenericArgument val[10] = { QGenericArgument() }; QVariant valIn[] = { val0, val1, val2, val3, val4, val5, val6, val7, val8, val9 }; for (int i = 0; i < parameterTypes.size(); i++) { if (!valIn[i].convert(QMetaType::type(parameterTypes[i].data()))) { LOGEVENT_ERR(QString("executeFunc convert param[%1] error!").arg(i)); } val[i] = QGenericArgument(parameterTypes[i].data(), &valIn[i].data_ptr().data); } //创建保存返回值的变量。 QGenericReturnArgument retArgument = QGenericReturnArgument(); Qt::ConnectionType connectType = Qt::AutoConnection; if (QString("void").compare(m.typeName())) { connectType = Qt::DirectConnection; ret = DeviceInterface::getParamVale("", m.typeName()); retArgument = QGenericReturnArgument(m.typeName(), &ret.data_ptr().data); LOGEVENT_DEBUG(QString("executeFunc call function[%1] direct.").arg(func)); } bRes = m.invoke(faceliving, connectType, retArgument, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9]); if (!bRes) LOGEVENT_ERR(QString("executeFunc call func[%1] error, object[%2]").arg(func).arg(faceliving->metaObject()->className())); } else { LOGEVENT_ERR(QString("executeFunc call func[%1] error, can't find func, object[%2]").arg(func).arg(faceliving->metaObject()->className())); Q_ASSERT(false); } return bRes; } void YHPostFaceLiving::connectEvent(QObject *dc, const QObject *receiver, const char *member) { connect(dc, SIGNAL(deviceevent(QObject*,QString,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant)), receiver, member, Qt::QueuedConnection); } void YHPostFaceLiving::get_remoteParam(QString result) { emit_deviceevent("remoteParam(QString)", result); } void YHPostFaceLiving::get_imageCompResult(QString result) { emit_deviceevent("imageCompResult(QString)", result); } void YHPostFaceLiving::get_programResult(QString serName, QString result) { emit_deviceevent("programResult(QString,QString)", serName, result); } void YHPostFaceLiving::get_programFail(QString serName, QString result) { emit_deviceevent("programFail(QString,QString)", serName, result); } void YHPostFaceLiving::get_getImageData(QString imageData) { emit_deviceevent("getImageData(QString)", imageData); } void YHPostFaceLiving::get_openComplete() { emit_deviceevent("openComplete()"); } void YHPostFaceLiving::get_closeComplete() { emit_deviceevent("closeComplete()"); } void YHPostFaceLiving::get_resetComplete() { emit_deviceevent("resetComplete()"); } void YHPostFaceLiving::get_error(int error) { emit_deviceevent("error(int)", error); } /* int YHPostFaceLiving::analyFmlFile() { if(faceliving){ QMap<QString,QString> funcParams; int ret = executeFunc("analyFmlFile()", funcParams).toInt(); return ret; } return 1; } void YHPostFaceLiving::loadenv(const QString &envPath) { if(faceliving){ QMap<QString,QString> funcParams; funcParams.insert("envPath", envPath); executeFunc("loadenv(QString)",funcParams); } } */ void YHPostFaceLiving::open() { if (faceliving) { QMap<QString, QString> funcParams; executeFunc("open()", funcParams); } else { emit_deviceevent("hardware_Error()"); } } bool YHPostFaceLiving::openSync() { if (faceliving) { QMap<QString, QString> funcParams; bool ret = executeFunc("openSync()", funcParams).toBool(); return ret; } else { return DeviceInterface::openSync(); } } void YHPostFaceLiving::close() { if (faceliving) { QMap<QString, QString> funcParams; executeFunc("close()", funcParams); } else { DeviceInterface::close(); } } bool YHPostFaceLiving::closeSync() { if (faceliving) { QMap<QString, QString> funcParams; bool ret = executeFunc("closeSync()", funcParams).toBool(); return ret; } else { return DeviceInterface::closeSync(); } } void YHPostFaceLiving::Reset(QString) { DeviceInterface::Reset(); } long YHPostFaceLiving::winId() { if (faceliving == NULL) return -1; QMap<QString,QString> funcParams; long ret = (long)executeFunc("winId()", funcParams).toInt(); return ret; } void YHPostFaceLiving::setParent(uint winid) { if (faceliving == NULL) return; QMap<QString,QString> funcParams; funcParams.insert("winid", QString("%1").arg(winid)); executeFunc("setParent(uint)", funcParams); } void YHPostFaceLiving::setGeometry(int x, int y, int width, int height) { if (faceliving == NULL) return; QMap<QString,QString> funcParams; funcParams.insert("x", QString("%1").arg(x)); funcParams.insert("y", QString("%1").arg(y)); funcParams.insert("width", QString("%1").arg(width)); funcParams.insert("height", QString("%1").arg(height)); executeFunc("setGeometry(int,int,int,int)", funcParams); } void YHPostFaceLiving::showDisplay(bool show) { if (faceliving == NULL) return; QMap<QString, QString> funcParams; funcParams.insert("show", QString("%1").arg(show)); executeFunc("showDisplay(bool)", funcParams); } QString YHPostFaceLiving::getTesoVersion() { if (faceliving == NULL) return QString(); QMap<QString, QString> funcParams; QString ret = executeFunc("getTesoVersion()", funcParams).toString(); return ret; } void YHPostFaceLiving::setTesoParam(const QString ¶ms) { if (faceliving == NULL) return; QMap<QString, QString> funcParams; funcParams.insert("params", params); executeFunc("setTesoParam(QString)", funcParams); } QString YHPostFaceLiving::getTesoParam() { if (faceliving == NULL) return QString(); QMap<QString,QString> funcParams; QString ret = executeFunc("getTesoParam()", funcParams).toString(); return ret; } void YHPostFaceLiving::setEndPoint(const QString &url) { Q_UNUSED(url); } void YHPostFaceLiving::getRemoteParam(const QString &info) { Q_UNUSED(info); } void YHPostFaceLiving::faceCompare(const QString ¶ms) { Q_UNUSED(params); } QString YHPostFaceLiving::getDevicePublicKey() { if (faceliving == NULL) return QString(); QMap<QString,QString> funcParams; QString ret = executeFunc("getDevicePublicKey()", funcParams).toString(); return ret; } bool YHPostFaceLiving::importDefaultCDK(QString cdk) { if (faceliving == NULL) return false; QMap<QString,QString> funcParams; funcParams.insert("cdk", cdk); bool ret = executeFunc("importDefaultCDK(QString)", funcParams).toBool(); return ret; } QString YHPostFaceLiving::getCDKCheckValue() { if (faceliving == NULL) return QString(); QMap<QString,QString> funcParams; QString ret = executeFunc("getCDKCheckValue()", funcParams).toString(); return ret; } bool YHPostFaceLiving::importWorkKey(QString key) { if (faceliving == NULL) return false; QMap<QString, QString> funcParams; funcParams.insert("key", key); bool ret = executeFunc("importWorkKey(QString)", funcParams).toBool(); return ret; } QString YHPostFaceLiving::getCameraStatus() { if (faceliving == NULL) return QString(); QMap<QString, QString> funcParams; QString ret = executeFunc("getCameraStatus()", funcParams).toString(); return ret; } bool YHPostFaceLiving::echoFaceImage(bool showOrCollect) { #ifdef Q_OS_WIN return false; #else if (faceliving == NULL) return false; QMap<QString,QString> funcParams; funcParams.insert("showOrCollect",QString("%1").arg(showOrCollect)); bool ret = executeFunc("echoFaceImage(bool)", funcParams).toBool(); return ret; #endif } void YHPostFaceLiving::startCamera() { if (faceliving == NULL) return; QMap<QString,QString> funcParams; executeFunc("startCamera()", funcParams); } void YHPostFaceLiving::stopCamera() { if (faceliving == NULL) return; QMap<QString,QString> funcParams; executeFunc("stopCamera()", funcParams); } void YHPostFaceLiving::capture() { if (faceliving == NULL) return; QMap<QString,QString> funcParams; executeFunc("capture()", funcParams); } QString YHPostFaceLiving::errorStr(int errNo) { if (faceliving == NULL) return QString(); QMap<QString, QString> funcParams; funcParams.insert("errNo", QString("%1").arg(errNo)); QString ret = executeFunc("errorStr(bool)", funcParams).toString(); return ret; } bool YHPostFaceLiving::setTuxedoParan(const QString &tag, const QString &value) { if (faceliving == NULL) return false; QMap<QString,QString> funcParams; funcParams.insert("tag",tag); funcParams.insert("value",value); bool ret = executeFunc("setTuxedoParan(QString,QString)", funcParams).toBool(); return ret; } QString YHPostFaceLiving::getTuxedoParan(const QString &tag) { if (faceliving == NULL) return QString(); QMap<QString, QString> funcParams; funcParams.insert("tag", tag); QString ret = executeFunc("getTuxedoParan(QString)", funcParams).toString(); return ret; } void YHPostFaceLiving::loadEnv(const QString &envPath) { if (faceliving == NULL) return; QMap<QString, QString> funcParams; funcParams.insert("envPath", envPath); executeFunc("loadEnv(QString)", funcParams); } int YHPostFaceLiving::tuxedoCommuncation(const QString &service, const QString &buff, const QString &reStr, int rcvlenth) { if (faceliving == NULL) return 0; QMap<QString, QString> funcParams; funcParams.insert("service", service); funcParams.insert("buff", buff); funcParams.insert("reStr", reStr); funcParams.insert("rcvlenth", QString("%1").arg(rcvlenth)); int ret = executeFunc("tuxedoCommuncation(QString,QString,QString,int)", funcParams).toInt(); return ret; } bool YHPostFaceLiving::analysFmlFile(const QString &fmlpath) { if (faceliving == NULL) return false; QMap<QString, QString> funcParams; funcParams.insert("fmlpath",fmlpath); bool ret = executeFunc("analysFmlFile(QString)", funcParams).toBool(); return ret; } QByteArray YHPostFaceLiving::formatBuff(const QString &buff) { if (faceliving == NULL) return QByteArray(); QMap<QString, QString> funcParams; funcParams.insert("buff", buff); QByteArray ret = executeFunc("formatBuff(QString)", funcParams).toByteArray(); return ret; } int YHPostFaceLiving::sendBuff(const QString &serName, const QByteArray &buff, const QString &reStr) { if (faceliving == NULL) return 0; QMap<QString, QString> funcParams; funcParams.insert("serName", serName); funcParams.insert("buff", buff); funcParams.insert("reStr", reStr); int ret = executeFunc("sendBuff(QString,QByteArray,QString)", funcParams).toInt();
//int ret = executeFucn("sendBuff(QString,QByteArray,QString)", QVariant(serName), QVariant(buff), QVariant(reStr)); return ret; }
本次代码修改之后,对元对象的功能作用,接口有了一定理解。
对动态库加载有了实践。
:-D