C interface example
Vance Shipley
vances@REDACTED
Wed Oct 6 23:04:20 CEST 1999
} I am looking for coding examples of how to
} communicate with an erlang program in C. ...
David,
I have just moved one of my applications off the Interface
Generator (ig-1.7.7) and on to a direct message pipe using
the erl_interface libraries.
There are two basic ways, as I see it, to link external
programs to Erlang/OTP; RPC and message passing. I have
opted for the latter. For the former you use IG or IC,
or implement your own using multiple pipes like below.
The following example code shows how to get a pipe up
between C and Erlang/OTP and pass messages across it.
I haven't figured out yet how to get the Erlang/OTP node
to connect to a listening C node. Can anyone give us a
hand with that?
-Vance
Motivity Telecom Inc.
#include <stdio.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/fcntl.h>
#include "erl_interface.h"
#include "ei.h"
#define PORT 6666 /* tcp port we listen on */
#define SELF(fd) erl_mk_pid(erl_thisnodename(), fd, 0, erl_thiscreation())
extern const char *erl_thisnodename(void);
extern short erl_thiscreation(void);
int sockfd, epmdfd; /* file descriptor of socket */
void endonsignal(int); /* handler for termination signals */
void endonsignal(int signo)
{
printf("termination on signal [%d]\n", signo);
erl_close_connection(sockfd);
erl_close_connection(epmdfd);
}
main()
{
struct in_addr addr;
struct sockaddr_in sin;
ETERM *arr[2], *answer, *cmsg, *pid;
int rc;
char buf[BUFSIZ];
ErlMessage emsg;
char **names;
int count;
int i;
ErlConnect remote;
int opt;
signal(SIGINT, endonsignal);
/* set unbuffered stdout */
setvbuf (stdout, NULL, _IONBF, NULL);
/* initialize the erl_eterm module */
erl_init(NULL, 0);
/* This is the short host name initialization routine */
printf("Initializing ...");
if(!erl_connect_init(69, "My Cookie String", 0))
erl_err_sys("erl_connect_init");
printf(" done.\n");
printf("node=%s, host=%s, alive=%s, creation=%d\n ",
erl_thisnodename(), erl_thishostname(),
erl_thisalivename(), erl_thiscreation());
/* This is the long host name initialization routine */ /*
printf("Initializing ...");
addr.s_addr = inet_addr("127.0.0.1");
if(!erl_connect_xinit("foo", "cnode", "cnode@REDACTED",
&addr, "My Cookie String", 0))
erl_err_sys("erl_connect_xinit");
printf(" done.\n");
*/
/* This is the short host name outgoing connect routine */
printf("Connecting ...");
if((sockfd = erl_connect("erlnode@REDACTED")) < 0)
erl_err_sys("erl_connect");
printf(" done.\n");
/* This is the long host name outgoing connect routine */ /*
printf("Connecting ...");
if((sockfd = erl_xconnect(&addr, "erlnode")) < 0)
erl_err_sys("erl_xconnect");
printf(" done.\n");
*/
/* This is the routine for listening for incoming connections
memset((char *) &sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(PORT);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
erl_err_sys("socket");
if(bind(sockfd, (struct sockaddr *) &sin, sizeof(sin)) <0)
erl_err_sys("bind");
if(listen(sockfd, 1) == -1)
erl_err_sys("listen");
*/
/* make the socket non-blocking */
/* opt = fcntl(sockfd, F_GETFL, 0);
if (fcntl(sockfd, F_SETFL, opt | O_NONBLOCK) == -1)
erl_err_sys("fcntl");
*/
/* This routine publishes our port number with epmd
if((epmdfd = erl_publish(PORT)) == -1)
erl_err_sys("erl_publish");
memset((char *) &remote, 0, sizeof(remote));
if(erl_accept(sockfd, &remote) == ERL_ERROR)
erl_err_sys("accept");
*/
/* register our name globally */
pid = SELF(sockfd);
if(erl_global_register(sockfd, "cnode", pid) != 0)
erl_err_sys("erl_global_register");
/* find registered names on node */
names = erl_global_names(sockfd, &count);
if(names == NULL)
erl_err_sys("erl_global_names");
else if(count) {
printf("Globally registered names:\n");
for(i=0; i < count; i++)
printf(" %s\n", names[i]);
}
free(names);
/* send a message */
/* arr[0] = SELF(sockfd);
arr[1] = erl_mk_atom("Hello world");
cmsg = erl_mk_tuple(arr, 2);
if(erl_reg_send(sockfd, "foo", cmsg) == 0)
erl_err_sys("erl_reg_send");
erl_free_term(cmsg);
*/
/* Receive a message */
while(1) {
rc = erl_receive_msg(sockfd, buf, BUFSIZ, &emsg);
switch(rc) {
case ERL_TICK:
printf("ERL_TICK received\n");
break;
case ERL_MSG:
printf("ERL_MSG received\n");
arr[0] = erl_mk_atom("goodbye");
arr[1] = erl_element(1, emsg.msg);
answer = erl_mk_tuple(arr, 2);
erl_send(sockfd, arr[1], answer);
erl_free_term(answer);
erl_free_term(emsg.msg);
erl_free_term(emsg.to);
break;
case ERL_ERROR:
erl_err_sys("erl_receive_msg");
default:
printf("unknown return value [%d]\n", rc);
break;
}
}
}
More information about the erlang-questions
mailing list