目录
一、使用Qt编译C动态库
二、使用QLibrary调用共享库
一、使用Qt编译C动态库
使用Qt新建一个C项目 cbb_frame,在项目中我们声明和定义两个函数,并导出函数。在cbb_mylog中我们使用了函数指针,这里为啥这样干,先埋个伏笔,下一篇我们再来具体交流下。
// cbb_frame.pro
TEMPLATE = lib #app
CONFIG += console \
# static \
c++11 \
shared\
dll
CONFIG -= app_bundle
CONFIG -= qt
CONFIG += no_debug_release # 不会生成debug 和 release 文件目录
DESTDIR = $$PWD/./_build/bin # 指定编译最终文件的生成路径
OBJECTS_DIR = $$PWD/./_build/obj # obj中间文件存放路径
MOC_DIR = $$PWD/./_build/moc # moc中间文件路径
RCC_DIR = $$PWD/./_build/rcc # rcc资源文件路径
UI_DIR = $$PWD/./_build/ui # ui_XXX.h 中间文件存放路径
DEFINES += CBB_LIBRARY # 导出
SOURCES += \
cbb_mylog.cpp
HEADERS += \
cbb_mylog.h
// cbb_mylog.h
#ifndef CBB_MYLOG_H
#define CBB_MYLOG_H
#if defined(CBB_LIBRARY)
# define _API extern "C" __declspec(dllexport)
#else
# define _API extern "C" __declspec(dllimport)
#endif
typedef void (*cbb_func)(void* ref,int len);
typedef struct cbb_data
{
cbb_func func;
void* ref;
int len;
}cbb_t,*p_cbb;
enum log_level{
LEVEL1,
LEVEL2,
LEVEL3
};
_API void cbb_mylog(p_cbb pb,log_level level,char* f,...);
_API int add(int x,int y);
#endif // CBB_MYLOG_H
// cbb_mylog.cpp
#include "cbb_mylog.h"
#include <stdio.h>
#include <stdarg.h>
void cbb_mylog(p_cbb pb, log_level level, char *f,...)
{
if ( nullptr != pb ) pb->func(pb->ref,pb->len);
char buf[4000] = {0};
va_list args;
va_start(args, f);
vsprintf(buf, f,args);
va_end(args);
printf("%s\n",buf);
}
int add(int x, int y)
{
return x+y;
}
二、使用QLibrary调用共享库
我们新建一个测试项目 LoadLib_Test
// LoadLib_Test.pro
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
CONFIG += no_debug_release # 不会生成debug 和 release 文件目录
DESTDIR = $$PWD/./_build/bin # 指定编译最终文件的生成路径
OBJECTS_DIR = $$PWD/./_build/obj # obj中间文件存放路径
MOC_DIR = $$PWD/./_build/moc # moc中间文件路径
RCC_DIR = $$PWD/./_build/rcc # rcc资源文件路径
UI_DIR = $$PWD/./_build/ui # ui_XXX.h 中间文件存放路径
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
#include <QCoreApplication>
#include <QLibrary>
#include <QDebug>
typedef void (*cbb_func)(void* ref,int len);
typedef struct cbb_data
{
cbb_func func;
void* ref;
int len;
}cbb_t,*p_cbb;
enum log_level{
LEVEL1,
LEVEL2,
LEVEL3
};
typedef void (*cb_func)(p_cbb pb,log_level level,char* f,...);
typedef int (*padd)(int x,int y);
void show_help(void* ref,int len){
printf("%s %d show_help \n",__FILE__,__LINE__);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString library_path = QCoreApplication::applicationDirPath() + "/cbb_frame.dll";
QLibrary* L = new QLibrary(library_path);
if( nullptr == L) return -1;
if(! L->load()){
qDebug() << "[error:]" << L->errorString();
delete L;
L = NULL;
}
// ![1]
cb_func myprintf = (cb_func)L->resolve("cbb_mylog");
cbb_t cbb = {show_help,NULL,0};
myprintf(&cbb,LEVEL1,"%s","this is a call back frame between library and customer program");
// ![2]
padd add_func = (padd)L->resolve("add");
qDebug() << " add_func(3,7) = " << add_func(3,7);
L->unload();
return a.exec();
}
输出:
main.cpp 24 show_help # 在动态库中调用了测试用例中的help_show()方法
this is a call back frame between library and customer program
add_func(3,7) = 10