我們的**倉庫裡面存在很多c語言的庫,基於執行效率或工作量的考慮,我們不想
使用erlang重寫相關庫,我們想在erlang中像使用erlang庫一樣方便地使用c庫,
vcall(erlang版)正是在這種背景下出現的。vcall(erlang版本)後面簡稱
vcall。
使用vcall時,我們只需要呼叫register介面批量
或單個註冊我們要使用的函式,接下來我們就可以像使用erlang庫提供的函式一樣
使用被註冊函式。vcall支援動態替換和解除安裝c庫。
## 實現原理
vcall分為兩部分:erlang部分(erl_vcall.beam,npc.beam);c部分(erl_vcall.dll
或 erl_vcall.so)。兩部分之間使用連線符合nif相關約定。erlang部分對外(使用者)
提供函式註冊、動態替換c庫、清理c庫介面。c部分對erlang提供函式註冊、函式函式
呼叫、動態解除安裝c庫、動態載入c庫、更新函式索引等介面。
函式註冊(正常)過程:使用者把函式相關資訊傳給erlang;erlang呼叫c註冊介面;通過
動態庫名、函式名、函式形參型別及個數,獲取函式指標,並儲存在全域性變數中;erlang
將函式函式註冊資訊儲存到ets表中(防止函式重複註冊),並動態生成模組名、函式名、
形參個數和c函式一致的erlang**;更新c中的全域性變數的函式索引。
函式呼叫過程 :呼叫註冊函式過程中生成的erlang函式(參考下面vcall使用示例);
erlang呼叫c對應呼叫介面;c解析引數並做引數的型別轉換,以符合ffi的呼叫約定;
把引數、註冊時儲存的函式指標傳遞給ffi通用介面,然後把結果返回給erlang。
動態替換c庫過程:呼叫相關介面,解除安裝原有c庫並刪除檔案;拷貝新庫到原有位置,重新
註冊舊庫中被註冊的函式(註冊資訊從ets表中獲取)。
## vcall使用示例
### 準備工作
erlang執行環境;vcall庫編譯生成對應檔案,並放到相應目錄下;被測試c庫放到
erl_vcall.so(windows下erl_vcall.dll)同一目錄下。
### 被測試動態庫
被測試動態庫名稱為test(windows下test.dll,linux下test.so),原始碼如下
int add(int* a, int* b)
int* createint(int a)
void destroyint(int* p)
int add2(int a, int b)
### 函式註冊呼叫過程
呼叫npc:start_link().啟動lpc模組(只需要執行一次)。
呼叫npc:register("test","int","add2","int,int",syn)註冊函式。
接下來就可以使用 test:add(2,3)返回計算結果5。
其他函式的註冊呼叫方法和上面的示例步驟一致。
## 效能測試
### 測試函式
int* createint(int a);
int add2(int,int);
int add3(double,double);
int multidouble(double,double,double,double,double,
double,double,double,double,double,double,double,
double,double,double,double,double,double,double,double);
int multiint(int,int,int,int,int,int,int,int,int,int,
int,int,int,int,int,int,int,int,int,int);
### 測試方法
通過erlang庫函式呼叫以上函式1000000次,求出函式調總耗時和平均耗時;通過呼叫空函式1000000次,求出nif層消耗的總時間和平均時間。
### 測試結果
#### 32位
函式總耗時(微秒)
平均耗時(納秒)
createint
444226
444add2
419352
419add3
417791
417multiint
1041342
1041
multidouble
1356512
1356
nif層
56113
56#### 64位
函式總耗時(微秒)
平均耗時(納秒)
createint
341248
341add2
336733
336add3
302804
302multiint
1035253
1035
multidouble
1069095
1069
nif層
72439
72#### 結論
1.函式呼叫64位系統稍快於32位,nif層64位耗時比32位長
2.函式呼叫的時長與引數型別關係不大,呼叫時長隨引數個數的增加而增加
## 不足
目前vcall僅支援c基本資料型別,不支援複雜資料型別,不支援可變引數函式,
不支援函式過載。
ps:本文僅提供思路,原始碼並未開源恕不能提供。
跨語言的GRPC呼叫
這次我們測試go與python之間的grpc呼叫。go作為grpc的客戶端,python作為grpc的服務端。第一步 安裝go的grpc工具 第二步 安裝python的grpc工具 pip install grpcio tools首先新建hello.proto檔案,該檔案很簡單,就是定義了乙個服務介...
C語言跨檔案呼叫變數方法
extern用在變數或者函式的宣告前,用來說明 此變數 函式是在別處定義的,要在此處引用 extern宣告不是定義,即不分配儲存空間。也就是說,在乙個檔案中定義了變數和函式,在其他檔案中要使用它們,可以有兩種方式 使用標頭檔案,然後宣告它們,然後其他檔案去包含標頭檔案 在其他檔案中直接extern。...
thinkphp 跨模組呼叫
專案簡介 測試專案名為tp3.0 訪問 localhost tp3.0 安裝環境 windows apache mysql php 模組分組 測試時將模組分為兩組home,admin,根據需求還可以新增更多分組,比如 home,admin,user,article。一 跨模組呼叫例項 簡介 在ind...