別名是啥玩意?
在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;
void func_init(int *data)
{
printf("libplugin.so: func_init is called. \\n");
alias_data = data;
}
void func_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.so
typedef void (*pfunc_init)(int *);
typedef void (*pfunc_stage1)(void);
int data[100] = { 0 };
void main(void)
{
data[0] = 10;
data[1] = 20;
printf("data[0] = %d \\n", data[0]);
printf("data[1] = %d \\n", data[1]);
// open libplugin.so
void *handle = dlopen("./libplugin.so", RTLD_NOW);
if (!handle)
{
printf("dlopen failed. \\n");
return;
}
// get and call init function in libplugin.so
pfunc_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.so
pfunc_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 --shared plugin.c -o libplugin.so
gcc -m32 -o main main.c -ldl
執行結果:
data[0] = 10
data[1] = 20
libplugin.so: func_init is called.
libplugin.so: func_stage1 is called.
data[0] = 100
data[1] = 200
可以看一下動態鏈接庫的符號表:
readelf -s libplugin.so | grep data
可以看到alias_data
標識符,并且是在本文件中定義的全局變量。
-
編譯器
+關注
關注
1文章
1623瀏覽量
49108 -
變量
+關注
關注
0文章
613瀏覽量
28360 -
標識符
+關注
關注
0文章
12瀏覽量
7339
發布評論請先 登錄
相關推薦
評論