訂閱
糾錯(cuò)
加入自媒體

如何在在動(dòng)態(tài)鏈接庫中調(diào)用外部函數(shù)?

大家好,我是一個(gè)動(dòng)態(tài)鏈接庫!

這個(gè)名字,相信你一定早就如雷貫耳了。

在計(jì)算機(jī)早期時(shí)代,由于內(nèi)存資源緊張,我可是發(fā)揮了重大的作用!

不論是在 Windows 系統(tǒng)中,還是在 Unix 系列平臺上,到處都能見到我的身影,因?yàn)槲夷転榇蠹夜?jié)省很多資源啊,資源就是人民幣!

愉快的玩耍

比如:我的主人編寫了這么一段簡單的代碼:

# 文件:lib.c
#include <stdio.h>
int func_in_lib(int k)

   printf("func_in_lib is called ");
   return k + 1;

只要用如下命令來編譯,我就誕生出來了 lib.so,也就是一個(gè)動(dòng)態(tài)鏈接庫:

$ gcc -m32 -fPIC --shared -o lib.so lib.c

這個(gè)時(shí)候,主人隨便把我丟給誰,我都可以為他服務(wù),只要他調(diào)用我肚子里的這個(gè)函數(shù) func_in_lib 就可以了。

雖然目前你看到我提供的這個(gè)函數(shù)很簡單,但是道理都是一樣的,后面如果有機(jī)會,我就在這個(gè)函數(shù)里來計(jì)算機(jī)器人的運(yùn)動(dòng)軌跡,給你瞧一瞧!

例如:張三今天寫了一段代碼,需要調(diào)用我的這個(gè)函數(shù)。

張三這個(gè)人比較喜歡騷操作,明明他在編譯可執(zhí)行程序的時(shí)候,把我動(dòng)態(tài)鏈接一下就可以了,就像下面這樣:

$ gcc -m32 -o main main.c ./lib.so

但是張三偏偏不這么做,為了炫技,他選擇使用 dlopen 動(dòng)態(tài)加載的方式,來把我從硬盤上加載到進(jìn)程中。

咱們來一起圍觀一下張三寫的可執(zhí)行程序代碼:

# 文件:main.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef int (*pfunc)(int);
int main(int argc, char *agv[])

   int a = 1;
   int b;
   // 打開動(dòng)態(tài)庫
   void *handle = dlopen("./lib.so", RTLD_NOW);
   if (handle)
   {
       // 查找動(dòng)態(tài)庫中的函數(shù)
       pfunc func = (pfunc) dlsym(handle, "func_in_lib");
       if (func)
       {
           b = func(a);
           printf("b = %d ", b);
       }
       else
       {
           printf("dlsym failed! ");
       }
       dlclose(handle);
   }
   else
   {
       printf("dlopen failed! ");
   }
   return 0;

從代碼中可以看到,張三預(yù)先知道我肚子里的這個(gè)函數(shù)名稱是 func_in_lib,所以他使用了系統(tǒng)函數(shù) dlsym(handle, "func_in_lib"); 來找到這個(gè)函數(shù)在內(nèi)存中的加載地址,然后就可以直接調(diào)用這個(gè)函數(shù)了。

張三編譯得到可執(zhí)行文件 main 之后,執(zhí)行結(jié)果完全正確,很開心!

悲從中來

可是有一天,我遇到一件煩人的事情,我的主人說:你這個(gè)服務(wù)函數(shù)的計(jì)算過程太單調(diào)了,給你找點(diǎn)樂子,你在執(zhí)行的時(shí)候啊,到其他一個(gè)外部模塊里調(diào)用一個(gè)函數(shù)。

話剛說完,就丟給我一個(gè)函數(shù)名:void func_in_main(void);。

也就是說,我需要在我的服務(wù)函數(shù)中,去調(diào)用其他模塊里的函數(shù),就像下面這樣:

#include <stdio.h>
// 外部函數(shù)聲明
void func_in_main(void);
int func_in_lib(int k)

   printf("func_in_lib is called ");
   // 調(diào)用外部函數(shù)
   func_in_main();
   return k + 1;

那么這個(gè)函數(shù)在哪里呢?天哪,我怎么知道這個(gè)函數(shù)是什么鬼?怎么才能找到它藏在內(nèi)存的那個(gè)角落(地址)里?

不管怎么樣,主人修改了代碼之后,還是很順利的把我編譯了出來:

$ gcc -m32 -fPIC --shared -o lib.so lib.c

編譯指令完全沒有變化。

因?yàn)槲覂H僅是一個(gè)動(dòng)態(tài)鏈接庫,這個(gè)時(shí)候即使我不知道 func_in_main 函數(shù)的地址,也是可以編譯成功的。

只不過我要把這個(gè)家伙標(biāo)記一下:誰要是想使用我,就必須告訴我這個(gè)家伙的地址在哪里!,否則就別怪我耍賴。

1  2  下一頁>  
聲明: 本文由入駐維科號的作者撰寫,觀點(diǎn)僅代表作者本人,不代表OFweek立場。如有侵權(quán)或其他問題,請聯(lián)系舉報(bào)。

發(fā)表評論

0條評論,0人參與

請輸入評論內(nèi)容...

請輸入評論/評論長度6~500個(gè)字

您提交的評論過于頻繁,請輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無評論

暫無評論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號