erlang c 跨語言呼叫設計

2021-08-17 21:33:04 字數 2706 閱讀 1094

我們的**倉庫裡面存在很多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...