do_call(N, {call,M,F,A,group_leader()}, infinity)
gen_server:call({?NAME,Node}, {call,M,F,A,group_leader()}, infinity)
gen:call(Name, '$gen_call', {call,M,F,A,group_leader()}, Timeout)
{'$gen_call', {pid(), reference()}, {call,M,F,A,pid()}}
receive {Mref, Reply} -> erlang:demonitor(Mref, [flush]), {ok, Reply};
ErlMessage
,ETERM
兩個重要結構體:
* ``` typedef struct { union { Erl_Integer ival; Erl_Uinteger uival; Erl_LLInteger llval; Erl_ULLInteger ullval; Erl_Float fval; Erl_Atom aval; Erl_Pid pidval; Erl_Port portval; Erl_Ref refval; Erl_List lval; Erl_EmptyList nval; Erl_Tuple tval; Erl_Binary bval; Erl_Variable vval; Erl_Function funcval; Erl_Big bigval; } uval;
} ETERMhtml
* **`erl_interface.h`,`ei.h`幾個重要函數:** * ```ErlMessage emsg = {}``` ```erl_receive_msg(fd, 0, 0, &emsg)``` emsg.msg裏面存放的結構就是上面{'$gen_call', {pid(), reference()}, {call,M,F,A,pid()}}三元組,若是這裏是進行響應遠程節點的rpc:call的話返回須要構建{reference(), data}使用erl_send進行反饋給遠程節點 * ```erl_element(2, emsg.msg)``` 取元組emsg.msg中第2個位置上的ETERM*對象地址,注意查看C\C++源碼發現使用此方法以後就從元組中抽象移除了這個地址的遍歷指引,因此只要使用erl_element函數取出來的臨時指針對象都必須經過erl_free_term釋放,未取的不須要顯示調用刪除由於刪除元組會遍歷它全部子元素。這種相似於淺拷貝應用範疇 * ```erl_free_term(emsg.from) ``` ```erl_free_term(emsg.msg)``` 這兩行釋放必須存在 * rpc互通的數據最好是經過binary或者json可進行序列化,反序列化封裝與解析 * **** ## C節點(client) * ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include "erl_interface.h" #include "ei.h" int main(int argc, char **argv) { int fd; int loop = 1; int got; ErlMessage emsg; erl_init(NULL, 0); struct in_addr addr; addr.s_addr = inet_addr("127.0.0.1"); if (erl_connect_xinit("idril", "cnode", "cnode@127.0.0.1",&addr, "be3", 0) == -1){ erl_err_quit("erl_connect_xinit"); } if ((fd = erl_connect("temp@10.0.1.85")) < 0){ erl_err_quit("temp@10.0.1.85"); } fprintf(stderr, "Connected to temp@10.0.1.85\n\r"); while (loop) { got = erl_receive_msg(fd, 0, 0, &emsg); if (got == ERL_TICK) { } else if (got == ERL_ERROR) { loop = 0; } else { if (emsg.type == ERL_REG_SEND) { ETERM * fromp = erl_element(2, emsg.msg); ETERM * tuplep = erl_element(3, emsg.msg); ETERM * call = erl_element(1, tuplep); ETERM * mod = erl_element(2, tuplep); ETERM * func = erl_element(3, tuplep); ETERM * arg = erl_element(4, tuplep); /* print */ printf("遠程rpc:%s %s:%s\r\n", ERL_ATOM_PTR(call), ERL_ATOM_PTR(mod), ERL_ATOM_PTR(func)); /* 消息發送着進程pid(),與接收引用ref() */ ETERM* from = erl_element(1, fromp); ETERM* mref = erl_element(2, fromp); ETERM* resp = erl_format("{~w, ~i}", mref, 50001); erl_send(fd, from, resp); erl_free_term(emsg.from); erl_free_term(emsg.msg); erl_free_term(fromp); erl_free_term(tuplep); erl_free_term(call); erl_free_term(mod); erl_free_term(func); erl_free_term(arg); erl_free_term(from); erl_free_term(mref); erl_free_term(resp); } } } }
rpc:call('cnode@127.0.0.1', mod, func, [0]). 50001 (temp@10.0.1.85)3>