记录一个关于x265动态链接库的问题

问题描述

在网上下载了x265的源码,编译并安装了相关的include和lib文件,然后在雷神那里下载了一个最小x265应用的源码:https://blog.csdn.net/leixiaohua1020/article/details/42079101

下载下来后用g++ simplest_x265_encoder.cpp编译,报下面的错误,当然这很容易看出来是没有加链接库的原因。

root@localhost:~/simplest_encoder/simplest_x265_encoder# g++ simplest_x265_encoder.cpp
/usr/bin/ld: /tmp/ccWHthlJ.o: in function `main':
simplest_x265_encoder.cpp:(.text+0xb4): undefined reference to `x265_param_alloc'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0xc0): undefined reference to `x265_param_default'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x110): undefined reference to `x265_encoder_open_32'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x150): undefined reference to `x265_picture_alloc'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x160): undefined reference to `x265_picture_init'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x4cc): undefined reference to `x265_encoder_encode'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x574): undefined reference to `x265_encoder_encode'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x600): undefined reference to `x265_encoder_close'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x608): undefined reference to `x265_picture_free'
/usr/bin/ld: simplest_x265_encoder.cpp:(.text+0x610): undefined reference to `x265_param_free'
collect2: error: ld returned 1 exit status

当我加上链接库编译g++ simplest_x265_encoder.cpp -lx265出现如下结果:

root@localhost:~/simplest_encoder/simplest_x265_encoder# g++ simplest_x265_encoder.cpp -lx265
/usr/bin/ld: /tmp/ccF8r4R9.o: in function `main':
simplest_x265_encoder.cpp:(.text+0x110): undefined reference to `x265_encoder_open_32'
collect2: error: ld returned 1 exit status

发现问题

我去雷神的源码里找了半天,所有的include文件都找了都没有x265_encoder_open_32这个东西,踌躇了很久。当时唯一确定的是雷神的代码是没问题的,因为我在虚拟机上编译都能通过,放到嵌入式板子里不能通过。于是就再去看看源码,发现一个奇怪的地方,在编译生成的/usr/local/include/x265.h文件里面:

/* Force a link error in the case of linking against an incompatible API version.
 * Glue #defines exist to force correct macro expansion; the final output of the macro
 * is x265_encoder_open_##X265_BUILD (for purposes of dlopen). */
#define x265_encoder_glue1(x, y) x ## y
#define x265_encoder_glue2(x, y) x265_encoder_glue1(x, y)
#define x265_encoder_open x265_encoder_glue2(x265_encoder_open_, X265_BUILD)

其中的x265_encoder_glue2(x265_encoder_open_, X265_BUILD)这句就是造成undefined reference to x265_encoder_open_32'的关键,因为在你编译后的/usr/local/include/x265_config.h文件下有这个定义:

/* Incremented each time public API is changed, X265_BUILD is used as
 * the shared library SONAME on platforms which support it. It also
 * prevents linking against a different version of the static lib */
#define X265_BUILD 199

而且在每个平台下编译后的X265_BUILD结果都不一样,因此不能简单的去别的地方复制。

解决问题

所以最终的办法是将雷神源码里的x265_config.h文件删除。再编译就能通过啦:

g++ simplest_x265_encoder.cpp -lx265

然后看下编译出来的程序链接库信息:

root@localhost:~/simplest_encoder/simplest_x265_encoder# ldd a.out
        linux-vdso.so.1 (0x0000007f8cd6c000)
        libx265.so.201 => not found
        libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000007f8cbb4000)
        /lib/ld-linux-aarch64.so.1 (0x0000007f8cd3c000)
root@localhost:~/simplest_encoder/simplest_x265_encoder#

这里面说我的libx265.so找不到,那是因为/usr/local/lib不在查找路径下,所以将这个路径加进去:

vim /etc/ld.so.conf.d/usr-libs.conf # 在这个文件下写 /usr/local/lib
ldconfig # 使配置生效

最后就可以运行啦!!!!!!
RK3399运行结果:

x265 [info]: frame I:      1, Avg QP:28.32  kb/s: 375.60
x265 [info]: frame P:     13, Avg QP:28.88  kb/s: 546.22
x265 [info]: frame B:     36, Avg QP:34.70  kb/s: 94.83
x265 [info]: Weighted P-Frames: Y:0.0% UV:0.0%
x265 [info]: consecutive B-frames: 7.1% 7.1% 28.6% 35.7% 21.4%

我在rk3399上运行的编码帧率只有9帧左右,在虚拟机上编码的帧率有29帧左右。相差了3倍,而且这只是640*360的分辨率而已。由此可见H.265在实时编码的速度上还是太慢。

问题反思

#define x265_encoder_glue1(x, y) x ## y
#define x265_encoder_glue2(x, y) x265_encoder_glue1(x, y)
#define x265_encoder_open x265_encoder_glue2(x265_encoder_open_, X265_BUILD)

这三句代码是怎样将x265_encoder_open_, X265_BUILD结合在一块的呢?
主要就是靠#define x265_encoder_glue1(x, y) x ## y吧。

c++ANSI/ISO C中: ### 预处理运算符都是可用的。# 运算符会把 replacement-text 令牌转换为用引号引起来的字符串。

#include <iostream>
using namespace std;
#define MKSTR( x ) #x
int main ()
{
    cout << MKSTR(HELLO C++) << endl;
    return 0;
}

上面的运行结果是:HELLO C++
原理大概就是MKSTR(HELLO C++相当于"HELLO C++"

另外:## 运算符用于连接两个令牌。下面是一个实例:

#define CONCAT( x, y )  x ## y
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要调用MATLAB程序,你可以使用C语言中的动态链接库来实现。首先,你需要将MATLAB代码转换为动态链接库文件。你可以使用MATLAB开发者工具中的Library Compiler来完成这个过程。打开开发者工具,点击Library Compiler,选择你需要转换的MATLAB文件,然后生成相应的文件。生成的文件包括libmex.lib、libmx.lib、libmat.lib和mclmcrrt.lib等。\[1\] 将转换后的文件放入你的项目中,其中根目录文件夹下需要放置使用对象的.dll文件。然后,在你的代码中添加必要的头文件和库文件引用。使用#include "mclmcrrt.h"来初始化MATLAB运行时环境,并使用#pragma comment(lib, "*.lib")来链接相应的库文件。其中,*表示你转换的动态链接库名称。\[2\] 这只是一个简单的例子,用于演示如何使用MATLAB调用C语言生成的动态链接库。在实际工程中,你的动态链接库必须符合MATLAB的要求。你可以在MATLAB中使用loadlibrary()语句来检验你所生成的动态链接库文件是否有效。\[3\] #### 引用[.reference_title] - *1* *2* [踩坑记录C++调用matlab生成的动态链接库](https://blog.csdn.net/Z_122113/article/details/128332109)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [C语言生成可被MATLAB调用的动态链接库.Dll文件](https://blog.csdn.net/sinat_38835380/article/details/109519316)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值