C, C++, Obj-C

常用语言,主要用于win32 OpenGL等GUI程序和2D/3D图形编程,也会包含一些如Objective-C等相关物.

Win下搭建CLion配合远程Linux的联盛德W801开发环境(csky-elfabiv2-tools)

之前9块钱促销买了块海凌科(Hi-Link)的W801开发板HLK-W801-KIT-V1.1:

到手后看了各种资料用CDK IDE搭起了开发环境,简单试了试灯,还踩了个Upgrade Tools上传程序的坑:W801开发板Upgrade Tools上传程序失败问题,那之后这块板就吃灰了😂,最近因为发现网口WOL网络唤醒在电脑完全断电恢复后无法使用的问题(试了自己和朋友的几台电脑,华硕的x370主板、技嘉的x570主板、公司的技嘉z390主板都不行,网上看有人说自己的电脑可以掉电后WOL,介绍的各种设置方法也基本都试了个遍,无果), 打算研究个IoT远程开机功能,嘉立创的开源平台上一搜能搜到很多,但大都基于ESP的MCU,于是又想起了这块W801…不过用惯了VS、Xcode、CLion的我对之前使用CDK的体验着实不怎么样,在联盛德的官方论坛上也看到有人基于VSCode搭建了开发环境,有win下配msys的,也有走远程linux编译的,由于本人实在是对cgywin,mingw这类windows下移植linux环境的工具不感兴趣,所以这回打算尝试下远程linux编译的方式再次搭建下W801的开发环境,同时使用最近经常用的CLion IDE(我用的Nova版,写此文的时候还处于EAP状态,已经进入RC状态了,下载2024.1 RC版(设置中高级里启用ReSharper 引擎,重启后就是Nova办了),但实际测试并没发现什么严重问题,理论上稳定版对远程linux开发支持应该也是一样的),另外,多说一句,虽然说的是remote linux,其实WSL,或者本地虚拟机也都是一个道理,那下面我就记录下这样搭环境的主要步骤。

Continue reading…

VS 2022构建boost 1.57.0时的missing argument global-setup问题

最近要用到一个库,依赖boost,于是久违的下载了需求的最低版本1.57的boost拿来build一把,结果已开具就遇到了坑…

目前用的编译器是VS 2022的toolchain,于是打开x64 Native Tools命令行,进到boost源码路径,简单看了下说明,敲了“bootstrap.bat”,提示:

Building Boost.Build engine
cl: 命令行 warning D9035 :“GZ”选项已否决,并将在将来的版本中移除
cl: 命令行 warning D9036 :使用“RTC1”而不使用“GZ”
cl: 命令行 warning D9002 :忽略未知选项“/MLd”

Bootstrapping is done. To build, run:

    .\b2

To adjust configuration, edit 'project-config.jam'.
Further information:

    - Command line help:
    .\b2 --help

    - Getting started guide:
    http://boost.org/more/getting_started/windows.html

    - Boost.Build documentation:
    http://www.boost.org/boost-build2/doc/html/index.html
Continue reading…

也记一篇关于strncpy和snprintf中n的不同之处

关于这俩c库函数的使用方法,百度上一搜能搜到很多,但是实际上用了这么多年的我有时候还是会犯迷糊,分不清哪个是处理0结尾的,哪个是没有的,因此今天趁着放假有时间,再整理记录一下。

#include <cstring>

int main(int argc, char *argv[])
{
    char sz_test1[10] = {};
    char sz_test2[10] = {};

    char sz_source[10] = "123456789";

    strncpy(sz_test1, sz_source, 10);
    snprintf(sz_test2, 10, "%s", sz_source);

    return 0;
}

上面是一段很简单的写在cpp里的c代码,纯c也差不多,主要说的是这俩c函数的区别,可以看到sz_source有9个字符,带1个结尾0凑成10字节的字符串,上面还有两个同样是10字节的char缓冲区用于测试,可以看到strncpysnprintf的n都给10的时候,sz_test1和sz_test2都是和sz_source一样的结果,包括结尾0。

接下来把两个函数的n都换成9,这时候可以看到如下结果:

Continue reading…

关于Si4735的SSB Patch(pu2clr开源项目)

最近在研究基于Arduino + Si4735 + pu2clr/SI4735的数字收音机,FM功能基本已经ok了,感谢pu2clr开源项目作者 Ricardo Lima Caratti 封装了这么好用的库,电路连接正确的情况下,基本可以秒实现功能!

简单试玩了一段时间后准备挑战下传说中的SSB单边带补丁,结果踩到了一个小坑,使用pu2clr库中的代码:https://github.com/pu2clr/SI4735/blob/master/examples/TOOLS/SI47XX_09_SAVE_SSB_PATCH_EEPROM/SI47XX_09_SAVE_SSB_PATCH_EEPROM.ino,准备将SSB补丁写进AT24C256 eeprom中,结果发现执行代码后,数据写入出现了问题,所有验证过程读回的数据全都是0xFF,patch的name什么的在Arduino IDE的Serial Monitor中看到的也都是乱码,size也都是FF对应的错误数据65535这些…

Continue reading…

[续]Win10 + WSL编译FFmpeg开启openssl依赖时的坑

之前写过一篇基于WSL编译windows版FFmpeg的博文:使用Win10 + WSL编译FFmpeg时的依赖库处理 – https://blog.k-res.net/archives/2771.html,记录了一些基本构建操作和一些问题,但是当时的configure并没有开启很多其他依赖项来激活相关功能,这次要记录的是通过开启openssl的方式,增加如https,rtmps等协议的支持,虽然有WSL的加持,大大简化了windows下编译FFmpeg的复杂度,但到了某些依赖,如这次要说的openssl时,还是有些需要注意的地方的,毕竟WSL的方式实际的本质是在一个同时有linux命令但又能执行windows执行程序的特殊环境下执行构建操作,带来方便的同时也带来了一些特有的麻烦:

Continue reading…

OpenSSL EVP API实现MD5加密C++代码

网上找到的大部分都是旧API,新版OpenSSL推荐使用EVP系列接口,在此记录下EVP方式的MD5哈希实现代码:

#include "openssl/conf.h"
#include "openssl/evp.h"
#include "openssl/err.h"
#include "openssl/engine.h"

void handle_errors()
{
	ERR_print_errors_fp(stderr);
	abort();
}

std::string md5_str(const std::string & str)
{
	const auto * md = EVP_get_digestbyname("MD5");
	if (nullptr == md)
	{
		std::cerr << "Failed to EVP_get_digestbyname MD5!" << std::endl;
		return "";
	}

	unsigned char buf[EVP_MAX_MD_SIZE] = {};
	unsigned int olen = EVP_MAX_MD_SIZE;

	EVP_MD_CTX * ctx = EVP_MD_CTX_new();
	if (nullptr == ctx)
	{
		std::cerr << "Failed to EVP_MD_CTX_new!" << std::endl;
		return "";
	}
	if (1 != EVP_DigestInit(ctx, md))
	{
		handle_errors();
		return "";
	}
	if (1 != EVP_DigestUpdate(ctx, str.data(), str.length()))
	{
		handle_errors();
		return "";
	}
	if (1 != EVP_DigestFinal(ctx, buf, &olen))
	{
		handle_errors();
		return "";
	}
	EVP_MD_CTX_free(ctx);

	return { reinterpret_cast<char*>(buf), olen };
}

int main()
{
	OpenSSL_add_all_digests();
	const std::string plain = "test1234";
	const std::string hash = md5_str(plain);
	std::cout << "plain: " << plain << " md5 hash: " << hash << std::endl;
	return EXIT_SUCCESS;
}

后面有时间再增加AES等的EVP实现代码

一种FFmpeg提示“dts < pcr, TS is invalid“的解决方法

此问题出现在使用FFmpeg(动态库)输出UDP+TS流且开启muxrate输出CBR时,音频为aac编码,视频为264编码(libx264),视频部分使用vbv-bufsize及vbv-maxrate和nal-hrd=cbr编码CBR码流,可以看到程序刚跑起来FFmpeg的log回调就会疯狂报标题里提到的dts < pcr警告,这个警告的源码位置只有一个,就在libavformat\mpegtsenc.c的mpegts_write_pes这个函数里,但是读了下代码,也没看出来为什么会报这个警告,后来找到了这两篇参考:

FFMPEG转码音视频不同步情况总结 https://blog.csdn.net/liuchen1206/article/details/79461434

ffmpeg 奇葩问题2 https://blog.csdn.net/WaitForDone/article/details/78030095

其中第一篇参考文章里提到了编码速度问题,提到去掉B帧这个操作,而我的应用直接设置了zerolatency的tune相当于也是不带B帧的编码,第二篇文章提到了几个点,一开始直接放到了结果上,疯狂尝试各种qmin、qmax设置,结果都没有见效,而且实际发现我的视频码流并没有文章作者提到的编码出来的视频帧偏大的问题,其实用的就是默认的量化值,每帧大小也基本符合整体目标码率,最后百思不得其解时,试了下直接用ffmpeg命令行进行同样参数的编码操作,发现并没有报这个“dts < pcr”的警告,而且是跑了很长时间后也一次警告都没有,又结合了下第二篇参考文章中提到的delay设置,于是开始比较ffmpeg命令行程序的各种format、codec初始化操作参数,最后终于找到了问题:

Continue reading…

使用Win10 + WSL编译FFmpeg时的依赖库处理

Windows 10的Linux子系统WSL安装过程就不做赘述了,网上资料很多。

之前一直认为WSL只是以类似虚拟机或容器化的方式使得能在Windows上运行原生Linux程序,当然,也在WSL上做过如使用ndk交叉编译Android原生程序、动态库的操作,用起来还是挺方便的。直到最近研究FFmpeg的Windows版编译时才发现(参考自:https://www.bilibili.com/read/cv7058269/),原来WSL还有一个“大杀招”:直接运行Windows执行程序exe,如下图所示:

可以看到,在WSL内直接执行VS 2019的编译器程序cl,也是完全没有问题的,基于这种方法,FFmpeg官网上所说的用cygwin,mingw,msys之类的桥接环境构建Win版FFmpeg的麻烦就不复存在了,而且新版FFmpeg源码(博主用的4.3)的configure也做好了对这种编译方式的支持,参考上面的链接,制定上toolchain=msvc等相关参数,剩下的事和nix系统上构建一样就可以顺利完成了,简单方便!

不过,今天要记录的并不是WSL下编译Win版FFmpeg的问题,而是编译时如何引入其它依赖,如openssl,xml2等以获取更多功能支持,尤其是在Win环境下,这些其它依赖库的位置很有可能是一个很随意的位置,而在WSL环境下处理这种依赖的头文件、库文件搜索路径时是有坑的…

Continue reading…

关于linux系系统的动态库全局函数重名问题

最近在使用某几个知名厂商的对象存储C SDK时,发现由于这些SDK的内部实现其实基本是一样的,进而导致了各个SDK的so中都或多或少有些被大家共同喜爱的全局函数(符号)名称,最后引发了在部分环境中出现了调用A厂商SDK的上传函数时崩溃在了B厂商SDK的同名全局函数中的问题,最开始感觉很是莫名其妙,后来查了资料发现,首先gcc编译时默认会将全局变量、函数等符号导出在都动态库中,而同时全局函数的加载又是抢占式的,这点通过如下简单试验便可验证:

Continue reading…