Qt calls dynamic libraries in linux environment, pro project file loading library and QLibrary loading library two ways

QT calls dynamic libraries in different ways at compile time and runtime. It can be loaded in pro file or loaded with QLibrary class during compile time; runtime depends on environment variables, and the dynamic library can be directly copied to the executable file directory under windows, linux Need to configure fixed path or relative path to search dynamic library (ps:windows program searches dynamic library in the path of executable file by default, linux does not).

Load at compile time: Pro project file loads dynamic library so

INCLUDEPATH += library header file path
LIBS += -L PATH -lLIB, PATH is the path where the so library is located, LIB is the name of the library (-L is the library path, -l is the library name, for example, the library file is libReceiptPrint.so, -LReceiptPrint should be added later)
collect2:ld returned 1 exit status Solution: The library is not loaded correctly, check the library path, 32-bit or 64-bit, whether the library is the debug version or the release version, the slot function is not implemented, the constructor is defined And the destructor is not implemented.

INCLUDEPATH += /home/chw/HSCompany/HardWareTest/source/HardWareTest/HardWareTest/sores
CONFIG(debug,debug|release){
    
    
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Debug/bin/ -lReceiptPrint
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Debug/bin/ -lInfrared
}
else{
    
    
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Release/bin -lReceiptPrint
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Release/bin -lInfrared
}

cannot open shared object file: No such file or directory Solution:
Run the analysis of the cause of the error. The library path added in LIBS += -LPATH -l is used in the compilation and linking to generate the makefile. The runtime library path is in the environment Search in variables, linux will not search the current path, the library path can be added to the LD_LIBRARY_PATH variable (use LD_DEBUG=libs xxx to view the program search path);
after loading the library, the compilation is normal, but an error is reported when running, try to add environment variables, QT- Project on the left-Bulid-build environment, click add, variable LD_LIBRARY_PATH, value $(LD_LIBRARY_PATH): library file path; the
Insert picture description here
above is to add environment variables in qt, after the software is released, environment variables must be set in the linux system, otherwise it will Report the above error.

Load at compile time: QLibrary loads dynamic library so

Opportunity: It is convenient and quick to load the so dynamic library in the project file, but I have encountered a situation. When multiple so files are loaded, and multiple so files have functions with the same name, the linux system will take the first loaded one as the standard, and then load the later. Ignored, leading to confusion, many solutions, most of them need to recompile the library, here is the introduction of using the QLibrary class to load so, without recompiling so;
Introduction to QLibrary:
Use QLibrary to load a dynamic link library when the program is running, an instance of QLibrary Acting on a single shared library, the typical usage of the QLibrary library is to parse the exported symbol in a library and call the C function represented by the symbol. If the library is compiled by a C++ compiler, then the function must be packaged In the extern "C" block. And on the Windows platform, you also need to use the dllexport macro to modify the function.
Code example:

//例如动态库接口函数为:extern "C" int OpenPort(char* pcInPort, int iInBaud);
typedef int (*Cs_OpenPort)(char* , int );//根据动态库接口函数原型,定义一个函数指针类型
Cs_OpenPort OpenPort;//用新的类型定义一个变量

QLibrary m_ReceiptPrint;//实例化一个QLibrary对象
//加载动态库
m_ReceiptPrint.setFileName("ReceiptPrint");//关联动态库名称
bool isok = m_ReceiptPrint.load();//加载动态库,成功返回true,失败返回false
OpenPort = (Cs_OpenPort)m_ReceiptPrint.resolve("OpenPort");//解析并调用动态库的函数
int ret = OpenPort((char*)"port",38400);//到这里就可以调用动态库接口

ps: The QLibrary method has a large amount of code and is prone to errors. It is not recommended to use it in large quantities. The problem of multiple so libraries with functions with the same name must be avoided in the packaging stage.

Runtime search library path: fixed path

The linux system does not search the library files in the directory where the application is located by default, and uses the specified path to search for the dynamic library;
there are three ways to fix the path, generate temporary environment variables, write the current user configuration file, and write the system configuration file.
1. Can be executed in the terminal:
replace the = sign with the path of the library to verify whether it is an environment variable path problem. This method will fail after restarting the system;

export LD_LIBRARY_PATH=/usr/local/lib

2. Add the following statement to ~/.bashrc, it will be valid for the current user after restarting:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

3. There is another method that is effective for all users. Modify the shared library configuration file /etc/ld.so.conf, copy the library path to the file, and execute the following command to take effect immediately:

sudo ldconfig

Runtime search library path: relative path

There are many problems in the use of fixed paths, such as the need to modify the configuration file during deployment; when other programs rely on the same name library, but the library version is different, the program will not start up. I have encountered the QT library that teamviewer relies on on site. The name of the library is the same as the library we used when developing with QT, but the version is different, causing the program to fail.

Therefore, it is recommended to use a relative path. In the QT development stage, specify the search path of the library in the pro file, and use -rpath to specify the path as the library search path:

QMAKE_LFLAGS += -Wl,--rpath=./lib	#指定应用程序所在路径的相对路径为库搜索路径
QMAKE_LFLAGS += -Wl,--rpath=.		#指定应用程序所在路径为库搜索路径

Supplement 1

The qt environment loading library reports an error: undefined reference to symbol dlclose
Add the following content to the .pro file of the QT project:

LIBS += -ldl		#显式加载动态库的动态函数库

Supplement 2: QT loads the static library .a file

It can only be loaded in the pro file, not via QLibrary. The loading method in the pro file is similar to the dynamic library. For example, the static library name is libTool_Fun.a, and the loading method is as follows:

INCLUDEPATH += /home/chw/HSCompany/QSRM/Pdjserver/dbTest/dbTest//头文件所在路径
LIBS += -L /home/chw/HSCompany/QSRM/Pdjserver/dbTest/build-dbTest-Desktop_Qt_5_10_1_GCC_64bit-Debug/bin  -lTool_Fun//LIBS += -L 库路径 -l库名称

It can be used after including the header file. Note that the static library is directly compiled into the executable file, so there is no need to rely on the library after release.
ps1: When generating static libraries, the naming rule is lib***.a. The static library generated by qt uses this naming rule by default. Gcc compile-o should also use this naming rule to specify the static library file name, otherwise it will be loaded in qt. May fail.
ps2: When QT calls the static library compiled in c language, it finds that pro loaded the library successfully, but an error is reported when calling the interface. It may be a C++ and C compatibility issue. The static library interface in the header file is wrapped with extern "C":

extern "C" {
    
    
	//c静态库接口
}

The role of extern "C": instruct the compiler to compile this part of the code in C language instead of C++.

Guess you like

Origin blog.csdn.net/weixin_40355471/article/details/111143298