VAPS XT入门系列16:Linux下编译生成VAPSXT动态链接库.so文件并使用Qt动态加载

系列索引:VAPS XT4.2.1入门系列索引

开发环境

软件版本
OSDeepin 20.2
GCC8.3
Qt5.15.1
VAPS XT4.2.1

示例代码官方示例代码:C:\Presagis\VAPS_XT_4_2_1\Projects\Examples\DrawingIntegrationExample

首先按照VAPS XT4.2.1安装配置配置好开发环境。

Porting layer配置文件

先在C:\Presagis\VAPS_XT_4_2_1\Configs\Targets下有跨平台生成编译代码的配置文件*.cfg,因为目标平台是linux,所以我们在此使用linux64.cfg,复制一份并重命名为linux64_so.cfg表示用于编译linux64位平台下so文件。

配置文件由Presagis官方技术人员提供,我在其基础上修改一些参数。

导出代码

打开VAPS软件

default

点击文件中的新建

new

填入项目名称和项目文件保存位置

new done

下图为本文使用的官方示例

example

其中DrawingIntegration.vprj为示例过程文件,我们将其导入刚刚创建的新根项目中。

点击File -> Import into project ,准备导入

import

输入子项目位置

input

点击OK后软件会自动解析到根项目中,

open

选择代码运行的目标平台,即之前提到的配置文件linux64_so.cfg

target

选择需要生成代码的软件,右击选择生成代码和资源

generate

软件会自动生成代码,结果如下:

result

将所有代码复制到linux系统之下的任意文件夹中。

编译

先编译必须的库文件,因为东西不少,所以我写成脚本,这样编译的时候方便一些。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# !/bin/sh

cd /home/hyper/VAPS_XT_4_2_1/src/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/RT/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/Main/Default/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/XTObjects/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/XTTypes/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/ThirdParty/FreeType/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/ThirdParty/PNG/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/Utils/XTResourceCompiler/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/Integration/DrawingIntegration/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/Ports/Target/linux/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/Ports/Display/OpenGL/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/Ports/OS/linux/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

cd /home/hyper/VAPS_XT_4_2_1/src/ThirdParty/FTGL/make
cg_make.sh -tgt $1 -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects makefile.mak -$2

当然如果你是一个一个测试编译的话,就是报错缺少什么就添加什么。

使用方法为

1
sh build.sh linux64_so rebuild

接下来编译so文件,在源码中mak文件所在的文件夹中,打开终端执行:

1
cg_make.sh -tgt linux64_so -vrpjdir /home/hyper/VAPS_XT_4_2_1/Projects/StandardRootProjects HUDDrawingIntegrationExample.mak -rebuild

build

就会在源码文件夹内生成*.so文件。

先看一下是否生成成功:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ ldd -r HUDDrawingIntegrationExample_linux64_so.so
linux-vdso.so.1 (0x00007ffdd33de000)
libGLU.so.1 => /lib/x86_64-linux-gnu/libGLU.so.1 (0x00007ffb923b4000)
libGL.so.1 => /lib/x86_64-linux-gnu/libGL.so.1 (0x00007ffb9232d000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ffb921a9000)
libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007ffb92068000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ffb9205e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ffb91edb000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ffb91ebf000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffb91cfe000)
libGLdispatch.so.0 => /lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007ffb91c46000)
libGLX.so.0 => /lib/x86_64-linux-gnu/libGLX.so.0 (0x00007ffb91c13000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffb92a7a000)
libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007ffb91be9000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ffb91be4000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ffb91bc1000)
libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007ffb91bbc000)
libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007ffb91bb4000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007ffb91b9a000)

没有未定义的函数。

用file命令查看一下:

1
2
$ file HUDDrawingIntegrationExample_linux64_so.so 
HUDDrawingIntegrationExample_linux64_so.so: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=e19f9d860bd19b214e061697cbcf1655fdf03aec, stripped

Qt程序

基于Qt动态加载的程序代码详见:Qt动态加载VAPS XT编译生成的DLL文件

错误

这里指的是我遇到的错误。

Qt无法弹出窗口

现象就是点击打开文件按钮,应该弹出选择文件的窗口,但是界面卡死。实际上是弹出了窗口,但是这个窗口是透明的。

解决办法就是换个写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifdef Q_OS_WIN
QString fileName = QFileDialog::getOpenFileName(this, QStringLiteral("选择动态库"), QString(),QString("*.dll\n*.so\n*"));
#endif

#ifdef Q_OS_LINUX
QString fileName;
QFileDialog filedialog;
filedialog.setAcceptMode(QFileDialog::AcceptOpen);
filedialog.setViewMode(QFileDialog::List);
filedialog.setFileMode(QFileDialog::AnyFile);
filedialog.setWindowTitle(tr("选择动态库"));
filedialog.setDefaultSuffix("*.dll\n*.so\n*");
filedialog.setOption(QFileDialog::DontUseNativeDialog);
if(filedialog.exec()== QDialog::Accepted )
{
QStringList filePaths = filedialog.selectedFiles();
fileName =filePaths[0];
qDebug() << fileName;
}
#endif

加载完so后直接全屏

使用正常的步骤加载so后,so里面的内容直接占据了这个屏幕,但是位置没有变。

so

我们查看一下so文件是否正常。

ldd

可以看到有一个函数未定义,并且和Window有关。

查看一下函数相关信息:

1
2
$ c++filt _ZN11vxtPLWindowC2Ev
vxtPLWindow::vxtPLWindow()

这样就找到问题所在了。

测试

完整测试运行视频-B站

完整Qt代码在VAPS_XT中的dynamicload。

测试用的so由官方示例编译而来。

Qt动态加载VAPS XT编译生成的DLL文件使用的是同一份代码。同时提供测试DLL/so文件。