【发布时间】:2019-12-29 20:06:11
【问题描述】:
我正在编写一个使用libao 进行音频输出的应用程序。该部分 我调用 libao 的程序中的一部分存在于共享对象中:
// playao.c
// compile with: gcc -shared -o libplayao.so playao.c -lao -lm
#include <ao/ao.h>
#include <stdio.h>
#include <math.h>
void playao(void) {
int i;
unsigned char samps[8000];
ao_initialize();
ao_sample_format sf;
sf.bits = 8;
sf.rate = 8000;
sf.channels = 1;
sf.byte_format = AO_FMT_NATIVE;
sf.matrix = "M";
ao_device *device = ao_open_live(ao_default_driver_id(), &sf, NULL);
if(!device) {
puts("ao_open_live error");
ao_shutdown();
return;
}
for(i = 0; i < 8000; ++i) {
float time = (float)i / 8000;
float freq = 440;
float angle = time * freq * M_PI * 2;
float value = sinf(angle);
samps[i] = (unsigned char)(value * 127 + 127);
}
if(!ao_play(device, (char *)samps, 8000)) {
puts("ao_play error");
}
ao_close(device);
ao_shutdown();
}
如果我在程序中链接到这个共享对象,它可以正常工作:
// directlink.c
// compile with: gcc -o directlink directlink.c libplayao.so -Wl,-rpath,'$ORIGIN'
void playao(void);
int main(int argc, char **argv) {
playao();
return 0;
}
但是,如果我使用dlopen/dlsym 来调用它,则没有错误,但是
程序不会发出任何声音:
// usedl.c
// compile with: gcc -o usedl usedl.c -ldl
#include <dlfcn.h>
#include <stdio.h>
int main(int argc, char **argv) {
void *handle = dlopen("./libplayao.so", RTLD_LAZY);
if(!handle) {
puts("dlopen failed");
return 1;
}
void *playao = dlsym(handle, "playao");
if(!playao) {
puts("dlsym failed");
dlclose(handle);
return 1;
}
((void (*)(void))playao)();
dlclose(handle);
return 0;
}
但是,运行 usedl 和 LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libao.so.4
确实工作。所以有一些关于 libao 的东西想要在
程序启动,不喜欢以后加载。
这是为什么?有什么办法可以解决这个问题,让 libao 工作 即使在程序执行的后期加载也正确?
如果重要的话,我正在运行 Debian 10 “buster”。
【问题讨论】:
标签: c audio dlopen dynamic-loading