成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C語言:如何給全局變量起一個別名?

開發 后端
這篇文檔通過兩個示例代碼,討論了如何在插件中(動態鏈接庫),通過別名來訪問真正的變量。

別名是啥玩意?

在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 <stdio.h>
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 <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
// 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標識符,并且是在本文件中定義的全局變量。

方法2:嵌入匯編代碼

在動態加載的插件中使用變量別名,除了上面演示的動態注冊的方式,還可以通過嵌入匯編代碼來: 設置一個全局標號來實現。

直接上示例代碼:

plugin.c源文件

#include <stdio.h>
asm(".Global alias_data");
asm("alias_data = data");
extern int alias_data[];
void func_stage1(void)
{
printf("libplugin.so: func_stage1 is called. \n");

*(alias_data + 0) = 100;
*(alias_data + 1) = 200;
}

main.c源文件

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
// 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 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 -rdynamic -o main main.c -ldl

執行結果:

data[0] = 10 
data[1] = 20
libplugin.so: func_stage1 is called.
data[0] = 100
data[1] = 200

也來看一下libplugin.so中的符號信息:

readelf -s libplugin.so | grep data

小結

這篇文檔通過兩個示例代碼,討論了如何在插件中(動態鏈接庫),通過別名來訪問真正的變量。

不知道您會不會有這樣的疑問:直接使用extern來聲明一下外部定義的變量不就可以了,何必這么麻煩?

道理是沒錯!

但是,在一些比較特殊的領域或場景中(比如一些二次開發中),這樣的需求是的確存在的,而且是強需求。

責任編輯:姜華 來源: IOT物聯網小鎮
相關推薦

2013-07-22 14:07:47

2022-04-12 11:38:06

C語言全局變量

2025-01-13 06:20:00

2010-11-12 10:08:55

SQL Server全

2013-07-25 15:15:26

iOS開發學習iOS全局變量

2013-07-17 16:16:06

Android全局變量定義全局變量Application

2010-03-09 14:12:55

Python全局變量

2024-09-04 08:55:56

2025-06-03 08:50:00

Static全局變量C 語言

2009-09-24 09:28:00

Scala講座全局變量scala

2009-11-06 13:28:19

Javascript框

2009-12-09 17:07:08

PHP unset全局

2010-02-01 14:28:37

Python全局變量

2020-11-09 14:10:38

Bug安全代碼

2015-01-07 14:41:32

Android全局變量局部變量

2009-12-04 13:14:19

PHP Global變

2021-12-30 06:59:27

視頻通話網頁

2024-05-29 08:49:22

Python全局變量局部變量

2023-12-07 12:59:46

C語言循環隊列代碼

2018-06-22 10:30:56

C語言虛擬機編譯器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一道本一区二区 | 亚洲天天干| 国产一区二区三区在线 | 一区二区三区成人 | 亚洲自拍一区在线观看 | 亚洲成人网在线观看 | 成人免费激情视频 | 日韩中文一区二区 | 色综合久| 亚洲免费在线视频 | 国产成人一区二区三区精 | 久久免费视频在线 | 国产精品无码永久免费888 | 国产视频第一页 | 夏同学福利网 | 在线视频国产一区 | 日韩在线视频观看 | 国产 欧美 日韩 一区 | av电影一区| 365夜爽爽欧美性午夜免费视频 | 精品国产一区二区三区日日嗨 | 超碰在线免费公开 | 成年女人免费v片 | 九色 在线| 一区二区三区免费观看 | 亚洲精品99999 | 韩国电影久久 | 人人鲁人人莫人人爱精品 | 亚洲va中文字幕 | 精久久久久 | 97久久久 | 综合久久久久久久 | 亚洲精品 在线播放 | 99精品欧美一区二区蜜桃免费 | 一区二区三区亚洲 | 免费看黄色国产 | 国产福利观看 | 91精品国产综合久久婷婷香蕉 | 一级免费毛片 | 欧美不卡一区二区三区 | 国产亚洲精品精品国产亚洲综合 |