Erlang 与 c 函数 对接
来源:互联网 发布:淘宝详情页是什么 编辑:程序博客网 时间:2024/05/01 04:19
一种编程语言同其他的语言结合互操作,充分利用现有资源,是很常见的事情. 也有特定的编程语言很擅长同其他语言的结合,如LUA. 在Erlang中也有很多方法同其他的编程语言结合.如通过内链驱动,原生实现函数(NIF)等.
Erlang虚拟机中通过一种端口的对象概念同外部程序进行通信,外部程序在端口处取得数据进行处理,处理完成后再送回端口,Erlang虚拟机创建端口的进程会将请求数据发到端口,再等待收回结果.所以说这需要一个协议,有了协议不同的语言间就可以交互了.
下面有两个非常简单的c语言函数,准备再erlang中调用:
example1.c
1 int sum(int x,int y){ 2 3 return x + y; 4 } 5 6 int twice(int x){ 7 8 return x*2; 9 }
定义的规则如下:
1. sum(x,y) 的调用会被编译成字节序列 [1, x, y]
2. twice(x) 的调用会被编译成字节序列[2, x]
3. 所有的数据包都带有两个字节的长度头
4. 返回值,参数都是一个字节长度
有了上述的这几条约定,就应该可以完成简单的函数的调用了.接下来就是双方都按这些规则交换数据就可以了,也就是所谓的driver程序了.
example1_driver.c
<span style="font-size:14px;"> 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef unsigned char byte; 5 6 int main(){ 7 8 int function = 0; 9 int arg1 = 0; 10 int arg2 = 0; 11 int result = 0; 12 byte buf[100] = {0}; 13 14 while(read_cmd(buf) > 0){ 15 16 function = buf[0]; 17 18 if(function == 1){ 19 arg1 = buf[1]; 20 arg2 = buf[2]; 21 result = sum(arg1,arg2); 22 } else if(function == 2){ 23 arg1 = buf[1]; 24 result = twice(arg1); 25 }else{ 26 exit(0); 27 } 28 29 30 buf[0] = result; 31 write_cmd(buf,1); 32 } 33 } </span>上面是C语言端的实现逻辑,它会不断的从标准输入取得计算的数据,计算之后在输出到标准输出中,这里所谓的标准输入输出,也就是Erlang的port. Erlang的端口进程会负责启动这个C程序,同时对它进行管理,Erlang端口进程不在了,也会杀掉这个C程序, 当这个C程序意外的挂掉之后,Erlang也会负责重新启动它. 这里面还涉及到两个实现的具体函数,不会影响整个逻辑. 贴出来如下:
<span style="font-size:14px;"> 1 #include <unistd.h> 2 3 typedef unsigned char byte; 4 5 int read_cmd(byte *buf) 6 { 7 int len; 8 9 if(read_exact(buf,2) != 2) 10 return -1; 11 12 len = (buf[0] << 8 | buf[1]); 13 14 return read_exact(buf,len); 15 } 16 17 int write_cmd(byte *buf,int len) 18 { 19 byte li; 20 21 li = (len >> 8) & 0xff; 22 write_exact(&li,1); 23 li = len & 0xff; 24 write_exact(&li,1); 25 26 return write_exact(buf,len); 27 } 28 29 int read_exact(byte *buf,int len){ 30 int i = 0; 31 int got = 0; 32 33 do { 34 if((i = read(0,buf + got, len-got)) <= 0) 35 return i; 36 got = got + i; 37 }while(got < len); 38 39 return len; 40 } 41 42 int write_exact(byte *buf,int len){ 43 int i = 0; 44 int wrote = 0; 45 46 do{ 47 if((i = write(1,buf + wrote,len - wrote)) <= 0) 48 return i; 49 wrote = wrote + i; 50 }while(wrote < len); 51 52 return len; 53 } </span><span style="font-size:18px;"> </span>
Erlang 这边同样是按照规则实现函数调用:
example1.erl
<span style="font-size:14px;"> 1 -module(example1). 2 3 -export([start/0,stop/0]). 4 -export([twice/1,sum/2]). 5 6 start() -> 7 register(example1,spawn( 8 fun() -> 9 process_flag(trap_exit,true), 10 Port = open_port({spawn,"./example1"},[{packet,2}]), 11 loop(Port) 12 end)). 13 14 15 stop() -> 16 ?MODULE ! stop. 17 18 twice(X) -> call_port({twice,X}). 19 sum(X,Y) -> call_port({sum,X,Y}). 20 21 call_port(Msg) -> 22 ?MODULE ! {call, self(), Msg}, 23 receive 24 {?MODULE,Result} -> 25 Result 26 end. 27 28 loop(Port) -> 29 receive 30 {call, Caller, Msg} -> 31 Port ! {self(),{command,encode(Msg)}}, 32 receive 33 {Port,{data,Data}} -> 34 Caller ! {?MODULE,decode(Data)} 35 end, 36 loop(Port); 37 stop -> 38 Port ! {self(),close}, 39 receive 40 {Port,closed} -> 41 exit(normal) 42 end; 43 {'EXIT',Port,Reason} -> 44 exit({port_terminated,Reason}) 45 end. 46 47 encode({sum,X,Y}) -> [1,X,Y]; 48 encode({twice,X}) -> [2,X]. 49 50 decode([Int]) -> Int.</span>
下面的问题就是编译,试一试了:
erlc example1.erl
gcc -o example1 example1.c example_driver.c erl_comm.c
example1:start().
example:sum(23,43).
example:twice(10).
0 0
- Erlang 与 c 函数 对接
- [Erlang]Erlang与C的节点通信
- Erlang对接Google Translation API
- Erlang函数与模式匹配
- erlang与c通信全过程
- erlang的函数与流程控制【一】
- erlang的函数与流程控制【二】
- Erlang学习笔记(四)模块与函数
- Erlang函数与模式匹配(2)
- QtWebkit本地C++与JavaScript数据对接(映射)
- Erlang与C构建的节点通讯
- Erlang与C构建的节点通讯
- Erlang与C构建的节点通讯
- erlang与c之间的连接
- WeCenter 与 UCenter 对接
- C# 与 dll对接
- springMVC与app对接
- Python与Erlang函数性的对比(一)
- 配置GDB支持STL调试
- Spell checker
- ASP.NET MVC处理文件上传示例
- Java基本概念
- HibernateTemplate 方法
- Erlang 与 c 函数 对接
- Jvm gc collectors
- 8086汇编杂记
- 小珂的游戏
- JAVA设计模式之策略模式
- 南邮-2047(地铁换线)
- anagrams两种解法 用map来优化查找
- 实验二
- Js各种继承方法总结