Erlang调用C程序
来源:互联网 发布:第三帝国 知乎 编辑:程序博客网 时间:2024/06/01 11:00
本文是《Erlang程序设计》中的示例,因为C语言基础薄弱,理解这节花了一些时间,示例中的C程序分为三个文件,为了便于调试,我合并成了一个文”c.c”,而Erlang代码则叫”e.erl”,在代码中加入了一些便于理解的注释。
主要用到的Erlang函数为:open_port(PortName,[Opt])
参数其中PortName可以是下列选项中的一个:
{spawn,Command}
启动一个外部程序。Command是这个外部程序的名称。
{fd,In,Out}
允许一个Erlang进程访问Erlang使用的任何当前打开文件描述符。文件描述符In可以用作标准输入,文件描述符Out会在
Erlang工作空间之外运行。
参数Opt可以是下列选项中的一个:
{packet,N}
数据包(packet)前面有N(1/2/4)个字节长度计数(包头)。
stream
…
e.erl
-module(e).-export([start/0,stop/0,twice/1,sum/2,call_port/1,loop/1]).start() -> register(e,spawn(fun() -> process_flag(trap_exit,true), %% 启动一个名为c的外部可执行程序,{packet,2}表示根据包大小自动添加2字节的包头 Port = open_port({spawn,"./c"},[{packet,2}]), loop(Port) end)).stop() -> ?MODULE ! stop.sum(X,Y) -> call_port({sum,X,Y}).twice(X) -> call_port({twice,X}).call_port(Msg) -> ?MODULE ! {call,self(),Msg}, receive {?MODULE,Result} -> Result end.loop(Port) -> receive {call,Caller,Msg} -> %% 发送示例 :调用 e:sum(3,4),encode后向端口发送 {self(),{command,[1,3,4]}} 的消息内容, %% 端口驱动自动给消息内容加上两个字节的长度包头{0,3},表示消息内容有3个字节,然后把 {0,3,1,3,4} 发送给外部C程序 Port ! {self(),{command,encode(Msg)}}, receive %% 接收示例:返回{0,1,7},端口驱动移除长度包头{0,1},然后向相连进程发送一个{Port,{data,[7]}}的消息 {Port,{data,Data}} -> Caller ! {?MODULE,decode(Data)} end, loop(Port); stop -> Port ! {self(),close}, receive {Port,closed} -> exit(normal) end; {'EXIT',Port,Reason} -> exit({port_terminated,Reason}) end.encode({sum,X,Y}) -> [1,X,Y];encode({twice,X}) -> [2,X].decode([Int]) -> Int.
c.c
#include <stdio.h>#include <stdlib.h>#include <unistd.h>typedef unsigned char byte;int read_cmd(byte *buff);int read_exact(byte *buf,int len);int write_cmd(byte *buff,int len);int write_exact(byte *buf,int len);int sum(int x,int y);int twice(int x);int main() { int fn,arg1,arg2,result; byte buff[100]; while( read_cmd(buff) >0 ) { fn = buff[0]; if( fn == 1) { arg1 = buff[1]; arg2 = buff[2]; result = sum(arg1,arg2); } else if( fn == 2 ) { arg1 = buff[1]; result = twice(arg1); } else { exit(EXIT_FAILURE); } buff[0] = result; // fprintf(stderr,"buff_value: %i,%i,%i \n",buff[0],buff[1],buff[2]); write_cmd(buff,1); }}/* read_cmd函数两次调用了read_exact 例如标准输入里面有5个字节 {0,3,1,3,4} 第一次调用 read(0,buf,2) ,读取了头两个字节{0,3} 第二次调用 read(0,buf,3),读取了剩下的3个字节{1,3,4}*/int read_cmd(byte *buf) { int len; if( read_exact(buf,2) !=2 ) return(-1); // "<<" 左移 ,二进制的向左移8位,n<<8 十进制表示 n * 2^8 ;"|" 按位或 len = (buf[0] << 8) | buf[1]; return read_exact(buf,len);}// 从标准输入读取 len 个字节int read_exact(byte *buf,int len) { int i,got=0; do { if(( i = read(0,buf+got,len-got)) <=0 ) return(i); got += i; } while ( got < len ); return(len);}/*例如:this->sum(3,4),返回结果{7,3,4},调用三次write_exact,分别输出{0,1,7},前两个字节是包头,表示消息体内容长度为1,之后的是消息体内容*/int write_cmd(byte *buf,int len) { byte li; li = (len >> 8) & 0xff; // fprintf(stderr,"%d \n",li); out : 0 write_exact(&li,1); li = len & 0xff; // fprintf(stderr,"%d \n",li); out : 1 write_exact(&li,1); return write_exact(buf,len);}// 输出终端最多 len 个字节int write_exact(byte *buf,int len) { int i,wrote = 0; do { if( (i=write(1,buf+wrote,len-wrote)) <= 0 ) return (i); wrote += i; } while (wrote<len); return(len);}// 求和int sum(int x,int y) { return x+y;}// 求2倍int twice(int x) { return 3*x;}
0 0
- Erlang调用C程序
- erlang调用c\c++动态链接库
- erlang调用外部程序如何得到其退出状态
- 汇编程序调用c程序
- c调用外部程序
- Matlab调用c程序
- java调用c程序
- MATLAB调用C程序
- Matlab调用C程序
- matlab调用c程序
- matlab调用C程序
- c++调用c程序
- Python调用C程序
- matlab调用C程序
- C++调用C程序
- matlab调用C程序
- python调用C程序
- matlab调用C程序
- linux Socket编程实例
- mysql常用知识
- Phalcon2.0.x 和 Laravel5 PHP框架性能测试
- Python及其包安装
- 一款非常好看的下载动画
- Erlang调用C程序
- 6.类(2)--类的成员
- Android设备获取唯一标识符
- 关于php+mysql+nginx配置的一点总结
- Android拍照、相册 获取图片后,裁剪图片
- Unity3d 简单实现物体旋转缩放移动
- 理解Angular中的$apply()以及$digest()
- bcd码和16进制的区别
- collectionView纯代码使用