【发布时间】:2016-05-30 14:05:41
【问题描述】:
ALSA 库包含两个 API 版本,通过定义 ALSA_PCM_OLD_HW_PARAMS_API 来访问旧版本启用。它采用了一些高级技巧(使用 .symver 汇编指令)来使单个 C 库能够包含不同的函数,具有相同的名称但不同的参数(对于新旧 API)。这一切都很好,但在某些情况下会引起麻烦。
例如,让我们创建两个源文件。第一个是main.cpp:
#include <alsa/asoundlib.h>
void lib_func();
void local_func()
{
int err;
unsigned int rate = 22050;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
snd_pcm_hw_params_alloca(¶ms);
assert(snd_pcm_open(&handle, "default", snd_pcm_stream_t(0), 0) >= 0);
assert(snd_pcm_hw_params_any(handle, params) >= 0);
err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
printf("err out of lib: %d\n", err);
snd_pcm_close(handle);
}
int main(int argc, char *argv[])
{
local_func();
lib_func();
}
第二个是mylib.cpp:
#include <alsa/asoundlib.h>
void lib_func()
{
int err;
unsigned int rate = 22050;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
snd_pcm_hw_params_alloca(¶ms);
assert(snd_pcm_open(&handle, "default", snd_pcm_stream_t(0), 0) >= 0);
assert(snd_pcm_hw_params_any(handle, params) >= 0);
err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
printf("err in lib: %d\n", err);
snd_pcm_close(handle);
}
请注意,local_func() 和 lib_func() 的内容除了打印的消息外是相同的。
在 Linux 机器上(我们测试了 Ubuntu 12/gcc 4.6.3 和 Ubuntu 14/gcc 4.8.4)构建和运行:
g++ -shared -fPIC -o libmylib.so mylib.cpp && g++ main.cpp -lasound -L . -lmylib
LD_LIBRARY_PATH=. ./a.out
我们运行时得到的结果是:
err out of lib: 0
err in lib: 192000
这意味着snd_pcm_hw_params_set_rate_near 在两个代码模块之间的行为不同。在共享库中,它错误地调用了旧版本的函数,它期望unsigned int val作为采样率而不是新版本期望unsigned int *val,并返回一个采样率(192000,因为它不接受我们的输入)而不是错误代码。
我们找到了解决此问题的方法:在创建共享库时将-lasound 参数添加到链接器。但是,这仍然是一个错误,其中一些用户(例如,我们认为有这个确切问题的用户:http://www.linuxquestions.org/questions/programming-9/snd_pcm_hw_params_set_rate_near-returns-huge-value-900199/)可能会遇到程序编译和链接没有错误或警告但发生错误行为的情况。
谁能解释这里发生了什么,也许这个问题可以被确认为一个错误并修复?
【问题讨论】: