java.lang.UnsatisfiedLinkError: Error looking up function 错误处理
写了份C++视频流录制接口给Java调用,结果出现了运行期报错:“java.lang.UnsatisfiedLinkError: Error looking up function”。跟Java的同事分析,确定原因是JNA无法读取到库文件中的正确函数名。例如,我提供的头文件如下:#ifndef __RECORDER_API_H__#define __RECORDER_API_H__#include
·
写了份C++视频流录制接口给Java调用,结果出现了运行期报错:“java.lang.UnsatisfiedLinkError: Error looking up function”。跟Java的同事分析,确定原因是JNA无法读取到库文件中的正确函数名。例如,我提供的头文件如下:
#ifndef __RECORDER_API_H__
#define __RECORDER_API_H__
#include <iostream>
#include <cstring>
#include <vector>
/*
Function: Create a stream recorder instance
input_url: input video stream url
*/
void* StreamRecorderCreateInstance(const std::string input_url);
/*
function: Destroy the previously created instance, release all the allocated memories.
phandle: the instance pointer created by StreamRecorderCreateInstance()
*/
void StreamRecorderDestroyInstance(void* phandle);
/* Set base output file name, e.g. given base name is out.m3u8, the real output name list may be (given 10 minutes as the single file duration):
out_20200929102501.m3u8
out_20200929103501.m3u8
out_20200929104501.m3u8
...
*/
void SetBaseFileName(void *phandle, std::string filename);
/* Set single file duration, seconds as the unit, default value is -1, which will output just one file */
void SetSingleFileDuration(void *phandle, int duration = -1);
/* Read stream data from input url, and save a serious of output files acording to user defined filename and single file duration.
when start signal is received, recording will begin until stop signal is sent by the caller.
see the functions: SendStartSignal(), SendStopSignal().
*/
void StreamRecording(void* phandle);
/* Get the output filename list which is generated by current input_url stream recording.
If single file duration is set to be -1, then there would be just one element in the list.
If single file duration is a positive value, the filename list will keep changing as the recording taken forward
*/
std::vector<std::string> GetGeneratedFilenameList(void *phandle);
/* Send start signal to the stream recorders.
note: multiple stream recorder would share the same one start signal.
*/
void SendStartSignal();
/* Send stop signal to the stream recorders.
note: multiple stream recorder would share the same one stop signal.
*/
void SendStopSignal();
由于C++支持函数重载,因此编译器在编译函数的过程中,会将函数的参数类型等也加入到编译后的代码中,因此编译出来的动态链接库中所含的函数名称与原函数名称是不同的。通过nm libxxx.so查看so库中的函数名,结果如下图,可以看到以上头文件中定义的函数名称都已被修改。
JNA调用so库是不参考头文件的, 因此也无法获取到真实的函数名称,因此出现标题中的报错。考虑到C++的这一特性,我们的解决方案是,在对外提供的函数前面,声明extern "C",让编译器以C语言的形式编译接口。可以在每个函数的声明前面加上extern "C",这里为了简洁起见,直接用extern "C"包裹了整个头文件中的函数声明:
#ifndef __RECORDER_API_H__
#define __RECORDER_API_H__
#include <iostream>
#include <cstring>
#include <vector>
#ifdef __cplusplus
extern "C"
{
/*
Function: Create a stream recorder instance
input_url: input video stream url
*/
void* StreamRecorderCreateInstance(const std::string input_url);
/*..... 省略若干函数声明 ...... */
/* Send start signal to the stream recorders.
note: multiple stream recorder would share the same one start signal.
*/
void SendStartSignal();
/* Send stop signal to the stream recorders.
note: multiple stream recorder would share the same one stop signal.
*/
void SendStopSignal();
}
#endif
#endif
重新编译动态库,再次查看库文件中的函数名称,结果如下,可以看到,对外接口函数名称已变为与头文件定义一致。
JNA调用也OK了。
更多推荐
已为社区贡献2条内容
所有评论(0)