我有一些充满全局变量的C代码,我需要将它与我的项目链接在一起。这个外部项目是一个经常更新的实时项目,因此重写代码以使其更加多实例友好并不是一个简单的选择。举一个具体的例子,假设我们有库代码(忽略不安全!):
// foo.c
static char s_memory[256];
static int s_length;
void foo_init(char **mem)
{
*mem = s_memory;
}
void foo_calc(char *mem)
{
s_length = strlen(mem);
}
int foo_result()
{
return s_length;
}
使用如下:
// test_foo.c
char *data;
foo_init(&data);
strcpy(data, "Hello, world!");
foo_calc(data);
printf("%s is %d characters long!\n", data, foo_result());
这适用于单线程实例,但我们的团队希望在多线程环境中运行它,显然这是非常错误的:
char *data1;
char *data2;
foo_init(&data1);
foo_init(&data2);
strcpy(data1, "Hello, world!");
strcpy(data2, "Goodbye cruel world!");
foo_calc(data1);
foo_calc(data2);
printf("%s and %s are %d and %d characters long!\n",
data1, data2, foo_result(), foo_result());
我希望我们能做的就是:
char *data1;
char *data2;
FOO_HANDLE inst1 = new_instance("foo.so");
FOO_HANDLE inst2 = new_instance("foo.so");
inst1.foo_init(&data1);
inst2.foo_init(&data2);
strcpy(data1, "Hello, world!");
strcpy(data2, "Goodbye cruel world!");
inst1.foo_calc(data1);
inst2.foo_calc(data2);
printf("%s and %s are %d and %d characters long!\n",
data1, data2, inst1.foo_result(), inst2.foo_result());
如何实现这样的目标?
答案 0 :(得分:0)
最简单的解决方案是将_Thread_local
(或__thread
)放在每个全局上,并从其自己的线程访问每个实例。
可能有效的另一个方法是每次需要新实例时创建.so文件的新副本,dlopen
。或者你可以编写自己的ELF加载器,允许同一个库的多个实例(不像它听起来那么难)。
所有这些都是糟糕的黑客,你真的应该修复代码以删除所有全局变量。