日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
C語言:如何給全局變量起一個(gè)別名?

別名是啥玩意?

在stackoverflow上看到一個(gè)有趣的話題:如何給一個(gè)變量設(shè)置一個(gè)別名?(How to assign to a variable an alias?)

所謂的變量別名,就是通過通過不同的標(biāo)識(shí)符,來表示同一個(gè)變量。

我們知道,變量名稱是給程序員使用的。

在編譯器的眼中,所有的變量都變成了地址。

請(qǐng)注意:這里所討論的別名,僅僅是通過不同的標(biāo)識(shí)符來引用同一個(gè)變量。

與強(qiáng)符號(hào)、弱符號(hào)的概念沒有任何關(guān)系,那是另一個(gè)話題。

在上面這個(gè)帖子中,作者首先想到的是通過宏定義,對(duì)變量進(jìn)行重新命名。

這樣的做法,將會(huì)在編譯之前的預(yù)處理環(huán)節(jié),把宏標(biāo)識(shí)符替換為變量標(biāo)識(shí)符。

在網(wǎng)友回復(fù)的答案中,大部分都是通過指針來實(shí)現(xiàn):讓不同的標(biāo)識(shí)符指向同一個(gè)變量。

不管怎么說,這也算是一種別名了。

但是,這些答案有一個(gè)局限:這些代碼必須一起進(jìn)行編譯才可以,否則就可能出現(xiàn)無法找到符號(hào)的錯(cuò)誤信息。

現(xiàn)在非常流行插件編程,如果開發(fā)者想在插件中通過一個(gè)變量別名來引用主程序中的變量,這該如何處理呢?

本文提供兩個(gè)方法來實(shí)現(xiàn)這個(gè)目的,并通過兩個(gè)簡單的示例代碼來進(jìn)行演示。

方法1:反向注冊(cè)

之前我接觸過一些CodeSys的代碼,里面的代碼質(zhì)量真的是非常的高,特別是軟件架構(gòu)設(shè)計(jì)部分。

傳說:CodySys 是工控界的 Android。

其中有個(gè)反向注冊(cè)的想法,正好可以用在變量別名上面。

示例代碼中一共有 2 個(gè)文件:main.c和plugin.c。

main.c中定義了一個(gè)全局變量數(shù)組,編譯成可執(zhí)行程序main。

plugin.c中通過一個(gè)別名來使用main.c中的全局變量。

plugin.c被編譯成一個(gè)動(dòng)態(tài)鏈接庫,被可執(zhí)行程序main動(dòng)態(tài)加載(dlopen)。

在plugin.c中,提供一個(gè)函數(shù)func_init,當(dāng)動(dòng)態(tài)庫被main dlopen之后,這個(gè)函數(shù)就被調(diào)用,并且把真正的全局變量的地址通過參數(shù)傳入。

這樣的話,在插件中就可以通過一個(gè)別名來使用真正的變量了(比如:修改變量的值)。

本質(zhì)上,這仍然是通過指針來進(jìn)行引用。

只不過利用動(dòng)態(tài)注冊(cè)的思想,把指針與變量的綁定關(guān)系在時(shí)間和空間上進(jìn)行隔離。

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

執(zhí)行結(jié)果:

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

可以看一下動(dòng)態(tài)鏈接庫的符號(hào)表:

readelf -s libplugin.so | grep data

可以看到alias_data標(biāo)識(shí)符,并且是在本文件中定義的全局變量。

方法2:嵌入?yún)R編代碼

在動(dòng)態(tài)加載的插件中使用變量別名,除了上面演示的動(dòng)態(tài)注冊(cè)的方式,還可以通過嵌入?yún)R編代碼來: 設(shè)置一個(gè)全局標(biāo)號(hào)來實(shí)現(xiàn)。

直接上示例代碼:

plugin.c源文件

#include 
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 
#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 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

執(zhí)行結(jié)果:

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

也來看一下libplugin.so中的符號(hào)信息:

readelf -s libplugin.so | grep data

小結(jié)

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

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

道理是沒錯(cuò)!

但是,在一些比較特殊的領(lǐng)域或場(chǎng)景中(比如一些二次開發(fā)中),這樣的需求是的確存在的,而且是強(qiáng)需求。


分享題目:C語言:如何給全局變量起一個(gè)別名?
網(wǎng)址分享:http://m.5511xx.com/article/dpppsse.html