参考文档:
《Programming Erlang》,第12章:Interfacing Techniques
创建C源文件:
hello.c 具体函数的实现
hello.c
int twice(int arg) { return (arg * arg); } int sum(int arg1, int arg2) { return (arg1 + arg2); }
hello_driver.c 驱动程序运行
hello_driver.c
#include <stdio.h> #define BUFFER_SIZE 100 typedef unsigned char byte; //8 bit int read_cmd(byte *buffer); int write_cmd(byte *buffer, int length); int main() { int function_number; //函数号 int arg1, arg2; //参数 int result; //结果 byte buffer[BUFFER_SIZE]; //缓冲区 while(read_cmd(buffer) > 0) { function_number = buffer[0]; switch(function_number) { case 1: //执行函数 twice arg1 = buffer[1]; result = twice(arg1); break; case 2: //执行函数 sum arg1 = buffer[1]; arg2 = buffer[2]; result = sum(arg1, arg2); break; default: // error break; } buffer[0] = result; write_cmd(buffer, 1); } return 0; }
erl_communication.c 与Erlang程序交互
erl_communication.c
1 #include <unistd.h> 2 3 typedef unsigned char byte; 4 5 int read_cmd(byte *buffer); 6 int write_cmd(byte *buffer, int length); 7 int read_exact(byte *buffer, int length); 8 int read_exact(byte *buffer, int length); 9 10 int read_cmd(byte *buffer) { 11 int length; //int 长度 16 bit 12 13 if(read_exact(buffer, 2) != 2) { 14 return -1; 15 } 16 length = (buffer[0] << 8) | buffer[1]; 17 18 return read_exact(buffer, length); 19 } 20 21 int write_cmd(byte *buffer, int length) { 22 byte li; //unsigned char 长度 8 bit 23 24 li = (length >> 8) & 0xff; 25 write_exact(&li, 1); 26 li = length & 0xff; 27 write_exact(&li, 1); 28 29 return write_exact(buffer, length); 30 } 31 32 int read_exact(byte *buffer, int length) { 33 int i, got = 0; 34 35 do { 36 /* 37 * read函数定义:ssize_t read(int fildes, void *buf, size_t nbyte); 38 * read函数描述:The read() function attempts to read nbyte bytes from the file associated with the open file descriptor, fildes, into the buffer pointed to by buf. 39 * 备注:fildes值0,标准输入 40 */ 41 if((i = read(0, (buffer + got), (length - got))) <= 0) { 42 return i; 43 } 44 got += i; 45 } while(got < length); 46 47 return length; 48 } 49 50 int write_exact(byte *buffer, int length) { 51 int i, wrote = 0; 52 53 do { 54 /* 55 * write函数定义:ssize_t write(int fildes, const void *buf, size_t nbyte); 56 * write函数描述:The write() function attempts to write nbyte bytes from the buffer pointed to by buf to the file associated with the open file descriptor, fildes. 57 * 备注:fildes值1,标准输出 58 */ 59 if((i = write(1, (buffer + wrote), (length - wrote)))) { 60 return i; 61 } 62 wrote += i; 63 } while(wrote < length); 64 65 return length; 66 }
创建Erlang源文件
hello.erl 创建进程,打开与C生成的可执行文件之间的端口,通过消息传递进行交互
Port = open_port(PortName, PortSettings)
open_port/2:http://www.erlang.org/doc/man/erlang.html#open_port-2
This returns a port. The following messages can be sent to a port:
Port ! {PidC, {command, Data}}
Send Data (an IO List) to the port.
Port !{PidC, {connect, Pid1}}
Change the PID of the connected process from PidC to Pid1.
Port ! {PidC, close}
Close the port.
hello.erl
1 -module(hello). 2 3 -export([start/0, stop/0]). 4 -export([twice/1, sum/2]). 5 6 -define(PORTNAME, ?MODULE). 7 8 start() -> 9 Fun = fun() -> 10 register(?PORTNAME, self()), 11 process_flag(trap_exit, true), 12 Port = open_port({spawn, "./hello"}, [{packet, 2}]), 13 loop(Port) 14 end, 15 spawn(Fun). 16 17 stop() -> 18 ?PORTNAME ! stop. 19 20 twice(X) -> call_port({twice, X}). 21 sum(X, Y) -> call_port({sum, X, Y}). 22 23 call_port(Message) -> 24 ?PORTNAME ! {call, self(), Message}, 25 receive 26 {?PORTNAME, Result} -> 27 Result 28 end. 29 30 loop(Port) -> 31 receive 32 {call, Caller, Message} -> 33 Port ! {self(), {command, encode(Message)}}, 34 receive 35 {Port, {data, Data}} -> 36 Caller ! {?PORTNAME, decode(Data)} 37 end, 38 loop(Port); 39 stop -> 40 Port ! {self(), close}, 41 receive 42 {Port, closed} -> 43 exit(normal) 44 end; 45 {'EXIT', Port, Reason} -> 46 exit({port_terminated, Reason}) 47 end. 48 49 encode({twice, X}) -> 50 [1, X]; 51 encode({sum, X, Y}) -> 52 [2, X, Y]. 53 54 decode([Int]) -> 55 Int.
编译C源文件,生成可执行文件
gcc -o hello hello.c hello_driver.c erl_communication.c
编译Erlang源文件,生成.beam文件
erlc hello.erl
转载于:https://www.cnblogs.com/dyingbleed/archive/2012/09/01/2666698.html