【问题标题】:how to link dll in qt如何在qt中链接dll
【发布时间】:2017-01-09 16:06:07
【问题描述】:

我在 .dll 和 .lib 中都有一个外部库,并且我有它的 .h 文件 库名称是'MTK_288_K001'[.dll|.lib|.h]

这是我的 qt.pro:

QT += core gui serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++14 static staticlib

TARGET = kiosk

TEMPLATE = app

SOURCES += main.cpp \
    mainwindow.cpp \
    serialport.cpp

RESOURCES += resources.qrc

win32: RC_ICONS = icon.ico

FORMS += mainwindow.ui

HEADERS += mainwindow.h \
    serialport.h

win32 {
    LIBS += -lMTK_288_K001
    LIBS += -L$$PWD/ -lMTK_288_K001
}

INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD

win32:!win32-g++: PRE_TARGETDEPS += $$PWD/MTK_288_K001.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/MTK_288_K001.lib

main.cpp

#include <QApplication>
#include "mainwindow.h"

#include "MTK_288_K001.h"

int main(int argc, char *argv[])
{
    MTK288KROpen("COM1");

    qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
    QCoreApplication::addLibraryPath("./plugins");
    QApplication a(argc, argv);
    MainWindow mw;
    mw.show();

    return a.exec();
}

MTK_288_K001.h

#define Bad_CommOpen -101
#define Bad_CommClose -105

#define OK                  0
#define ERR                 -1

#define Parameter_Error     -2
#define UpLoadErrorData     -3
#define UpLoadTimeOut       -4 
#define UpLoadCancel        -5 

#include <windows.h>

int APIENTRY GetSysVerion(char *strVerion);
HANDLE APIENTRY MTK288KUOpen();
int APIENTRY MTK288KUClose(HANDLE ComHandle);

int APIENTRY MTK288KUMultOpen(HANDLE DeviceHdlData[],int *DeviceNumbers);
int APIENTRY MTK288KUMultClose(HANDLE DeviceHdlData[],int DeviceNumbers);

int APIENTRY GetDeviceCapabilities(HANDLE ComHandle, int *_InputReportByteLength, int *_OutputReportByteLength);
int APIENTRY ReadACKReport(HANDLE ComHandle,  BYTE _ReportData[],BYTE _ReportLen);
int APIENTRY ReadUpReport(HANDLE ComHandle,  BYTE _ReportData[],BYTE _ReportLen);
int APIENTRY ReadReport(HANDLE ComHandle,  BYTE _ReportData[],BYTE _ReportLen);

int APIENTRY WriteReport(HANDLE ComHandle,  BYTE _ReportData[],BYTE _ReportLen);
int APIENTRY USB_ExeCommand(HANDLE ComHandle,BYTE TxCmCode,BYTE TxPmCode,int TxDataLen,BYTE TxData[],BYTE *RxReplyType,BYTE *RxStCode1,BYTE *RxStCode0,int *RxDataLen,BYTE RxData[]);


HANDLE APIENTRY MTK288KROpen(char *Port);
HANDLE APIENTRY MTK288KROpenWithBaut(char *Port, unsigned int Baudrate);
int APIENTRY MTK288KRClose(HANDLE ComHandle);
int APIENTRY RS232_ExeCommand(HANDLE ComHandle,BYTE TxCmCode,BYTE TxPmCode,int TxDataLen,BYTE TxData[],BYTE *RxReplyType,BYTE *RxStCode1,BYTE *RxStCode0,int *RxDataLen,BYTE RxData[]);


int APIENTRY USB_UpTrackData(HANDLE ComHandle,BYTE tracks,BYTE ReadMode,BYTE _WaitTime,BYTE *RxReplyType,int *_CardDataLen,BYTE _CardData[]);
int APIENTRY USB_Cancel_UpTrackData(HANDLE ComHandle);

int APIENTRY RS232_UpTrackData(HANDLE ComHandle,BYTE tracks,BYTE ReadMode,BYTE _WaitTime,BYTE *RxReplyType,int *_CardDataLen,BYTE _CardData[]);
int APIENTRY RS232_Cancel_UpTrackData(HANDLE ComHandle);

当我构建项目时,qt 给了我这个:

D:\kiosk\main.cpp:-1: error: undefined reference to `MTK288KROpen(char*)@4'

如何让 qt 在外部库中找到这个函数?

【问题讨论】:

  • 如果MTK_288_K001是C库,需要在#include "MTK_288_K001.h"周围加上extern "C" { }。无论如何,您可以使用dependency walker查看MTK_288_K001.dll中的符号并搜索“MTK288KROpen”或类似的东西。
  • 移除静态静态库
  • 即使在#include "MTK_288_K001.h" 周围删除static staticlibextern "C" { },qt 仍然给我这个错误。和'MTK288KROpen' 存在于dll文件中

标签: c++ qt dll shared-libraries


【解决方案1】:

根据您的评论,您的 DLL 中定义了符号 MTK288KROpen。 但是链接器抱怨 MTK288KROpen(char*)@4 没有定义。

这可能是由 HANDLE APIENTRY MTK288KROpen(char *Port) 函数的“错误”声明引起的。

正如我在评论中所说,添加extern "C" 应该通过使链接器查找MTK288KROpen 符号而不是MTK288KROpen(char*)@4 来解决问题。

我怀疑我之前在评论中提出的在#include "MTK_288_K001.h" 周围添加extern "C" { } 的建议不起作用,因为您已经在mainwindow.h 中包含MTK_288_K001.h

确保将extern "C" 添加到MTK_288_K001.h 中的MTK288KROpen 声明中,如下所示:

...
// This is C++ code so you cannot compile MTK_288_K001.dll anymore with this change, but it should work with your Qt app
extern "C" HANDLE APIENTRY MTK288KROpen(char *Port);
HANDLE APIENTRY MTK288KROpenWithBaut(char *Port, unsigned int Baudrate);
...

链接器不应再抱怨MTK288KROpen,但可能仍会抱怨其他功能。

如果您仍然对MTK288KROpen 有错误,请告诉我它是否是新的,以便我可以相应地更新我的答案。并告诉APIENTRY的值是什么。

如果有效,您有 2 个选项,具体取决于您是否可以编辑 MTK_288_K001.h

如果可以编辑,请像这样添加extern "C"

#ifdef __cplusplus
extern "C" {
#endif

[...]

#ifdef __cplusplus
}
#endif

如果不能,请创建一个中间文件 MTK_288_K001_CPP.h 并在 Qt 项目中使用它而不是 MTK_288_K001.h

extern "C"
{
#include "MTK_288_K001.h"
}

【讨论】:

  • 这是我的代码,我试过你说的。 github
  • 需要extern "C",但看起来MTK288K001.libMTK288K001.dll 不匹配,删除MTK288K001.lib 允许项目编译和链接。
  • 问题已修复。又出现了一个问题。程序在构建后无法运行。 qt 给The program has unexpectedly finished.
  • 使用调试器查看崩溃的位置。从您的代码来看,它可能是由MTK288KROpen("COM1") 引起的,因为字符串文字是const char *,但该函数需要char *,并且可能会尝试更改字符串文字。
  • 即使这个函数没有给出参数MTK288KUOpen() 程序也无法运行。我使用 qt 调试器运行,它给了我During startup program exited with code 0xc0000135. 我将 dll 文件复制到调试目录,但它对运行时没有任何影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 1970-01-01
  • 2018-05-23
  • 2016-10-18
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多