别名是啥玩意?
在stackoverflow
上看到一个有趣的话题:如何给一个变量设置一个别名?(How to assign to a variable an alias?
)
所谓的变量别名,就是通过通过不同的标识符,来表示同一个变量。
我们知道,变量名称是给程序员使用的。
在编译器的眼中,所有的变量都变成了地址。
请注意:这里所讨论的别名,仅仅是通过不同的标识符来引用同一个变量。
与强符号、弱符号的概念没有任何关系,那是另一个话题。
在上面这个帖子中,作者首先想到的是通过宏定义,对变量进行重新命名。
这样的做法,将会在编译之前的预处理环节,把宏标识符替换为变量标识符。
在网友回复的答案中,大部分都是通过指针来实现:让不同的标识符指向同一个变量。
不管怎么说,这也算是一种别名了。
但是,这些答案有一个局限:这些代码必须一起进行编译才可以,否则就可能出现无法找到符号的错误信息。
现在非常流行插件编程,如果开发者想在插件中通过一个变量别名来引用主程序中的变量,这该如何处理呢?
本文提供两个方法来实现这个目的,并通过两个简单的示例代码来进行演示。
文末有示例代码的下载地址。
方法1:反向注册
之前我接触过一些CodeSys
的代码,里面的代码质量真的是非常的高,特别是软件架构设计部分。
传说:CodySys 是工控界的Android。
其中有个反向注册的想法,正好可以用在变量别名上面。
示例代码中一共有 2 个文件:main.c
和plugin.c
。
main.c
中定义了一个全局变量数组,编译成可执行程序main
。
plugin.c
中通过一个别名来使用main.c
中的全局变量。
plugin.c
被编译成一个动态链接库,被可执行程序main
动态加载(dlopen
)。
在plugin.c
中,提供一个函数func_init
,当动态库被main
dlopen
之后,这个函数就被调用,并且把真正的全局变量的地址通过参数传入。
这样的话,在插件中就可以通过一个别名来使用真正的变量了(比如:修改变量的值)。
本质上,这仍然是通过指针来进行引用。
只不过利用动态注册的思想,把指针与变量的绑定关系在时间和空间上进行隔离。
plugin.c 源文件
#include
int*alias_data =NULL;voidfunc_init(int*data){printf("libplugin.so: func_init is called. \\n"); alias_data = data; }voidfunc_stage1(void){printf("libplugin.so: func_stage1 is called. \\n");if(alias_data) { alias_data[0] =100; alias_data[1] =200; } }
main.c 源文件
#include
#include
#include
// defined in libplugin.sotypedefvoid(*pfunc_init)(int*);typedefvoid(*pfunc_stage1)(void);intdata[100] = {0};voidmain(void){ data[0] =10; data[1] =20;printf("data[0] = %d \\n", data[0]);printf("data[1] = %d \\n", data[1]);// open libplugin.sovoid*handle =dlopen("./libplugin.so", RTLD_NOW);if(!handle) {printf("dlopen failed. \\n");return; }// get and call init function in libplugin.sopfunc_init func_init = (pfunc_init)dlsym(handle,"func_init");if(!func_init) {printf("get func_init failed. \\n");return; }func_init(data);// get and call routine function in libplugin.sopfunc_stage1 func_stage1 = (pfunc_stage1)dlsym(handle,"func_stage1");if(!func_stage1) {printf("get func_stage1 failed. \\n");return; }func_stage1();printf("data[0] = %d \\n", data[0]);printf("data[1] = %d \\n", data[1]);return; }
编译指令如下:
gcc-m32-fPIC--sharedplugin.c-olibplugin.sogcc-m32-omainmain.c-ldl
执行结果:
data[0] =10data[1] =20libplugin.so: func_init is called.libplugin.so: func_stage1is called.data[0] =100data[1] =200
可以看一下动态链接库的符号表:
readelf-s libplugin.so | grepdata
可以看到alias_data
标识符,并且是在本文件中定义的全局变量。
- 编译器
+关注
关注
1文章
1594浏览量
48868 - 变量
+关注
关注
0文章
604浏览量
28237 - 标识符
+关注
关注
0文章
12浏览量
7326
发布评论请先登录
相关推荐
评论