c - 如何从其他 C 程序访问共享对象(.so)中的全局变量?
问题描述
如标题所述,我正在尝试从普通 C 程序访问 .so 中的全局变量。
预加载.h:
int var;
void setting(int x);
测试.c:
#include "preload.h"
extern int var;
int main(){
...
setting(x);
/* use var */
}
我预计var
设置后x
仍为var
0。
编译:
gcc test.c -o test
gcc -shared -fPIC preload.c -o preload.so -ldl
执行:
LD_PRELOAD=$PWD/preload.so ./test
解决方案
这段代码在你的test.c
...
extern int var;
...声明有一个类型的对象,由整个程序中某处定义int
的名称标识。var
这段代码在你的preload.h
...
void setting(int x);
... 完全构成了另一个声明所承诺的定义,并且它出现在每个包含标题的翻译单元中,包括test.c
. 这使得声明变得test.c
多余,但 C 允许这样做。这也意味着程序test
提供了自己的对象var
。
如果您preload.c
还包括preload.h
,那么它还包含var
. 如果你将这两个翻译单元组合成一个程序,那么你就违反了 C 对一个程序包含多个相同标识符的外部定义的明确禁止。未定义的行为结果,您实际观察到的只是轻微的情况。
使您的main()
函数能够使用与var
您的函数相同的对象的正确方法setting()
是
明确声明
var
in :preload.h
extern
extern int var;
与不包括初始化程序的声明一起,导致声明不能用作定义。这种形式始终是您想在头文件中使用的形式。
将
var
at 文件范围的定义放入preload.c
(或任何应被视为拥有该变量的翻译单元中):int var;
(可选)删除
var
from的冗余声明test.c
。
但是请注意,这可以实现一个var
程序的不同部分之间的共享,包括库中的函数、共享的或静态的。根据您的示例,我认为这就是“来自其他 C 程序”的意思。另一方面,如果您的意思是要在不同的程序之间共享数据,那么将外部对象放入共享库将无法实现。使用此类共享库的每个程序的每个实例仍将获得这些对象的自己的副本。
如果实际上想要跨程序共享数据,那么您将需要为此使用特定于操作系统的机制。Linux 有两种共享内存,System V 和 POSIX。我会推荐后者。但是,如何使用它的详细信息将是另一个答案,而且您已经可以在 StackOverflow 和其他地方多次找到该答案。
推荐阅读
- reactjs - 为什么 e.preventDefault() 在 React 中不起作用?
- c# - 替换excel单元格中的字符
- sql - SQL OR Linq:当类别改变时如何分类成不同的批次
- dart - 如何检测 Flutter 中的 TabBar 变化?
- python - “x += y”与“x = x + y”的 FLOP 计数
- sql - 从多个表中查询产品并合并结果的最高效方式?
- javascript - 如何从 Psql 数据库转换日期列的显示视图
- javascript - 将表单输入复制到新的引导选项卡中
- c# - C# 打印浮点值 -0.0 错误
- ruby-on-rails - 通过嵌套子字段获取父对象过滤器