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