How to change a C-Node written with ei to be a port program?

Shawn Pearce spearce@REDACTED
Thu Mar 11 02:02:04 CET 2004


Set the port in binary mode and with a packet format of 3:

	open_port({spawn, "myprogram"}, [binary, {packet, 3}])

When you send/receive through it, use term_to_binary and binary_to_term
in Erlang:

	port_send(Port, term_to_binary(Message)),

	receive
	{Port, {data, Data}} ->
		Message = binary_to_term(Data)
	end

Within your C code, you need to do something like this:

	static int safe_read (int fd, char* buf, int len)
	{
		int		tot = 0;
		int		r;

		while (len > 0)
		{
			r = read(fd, buf, len);
			if (-1 == r)
			{
				return -1;
			}

			if (0 == r)
			{
				return 0;
			}

			tot += r;
			buf += r;
			len -= r;
		}

		return tot;
	}

	int main (int argc, char* argv)
	{
		int		msg_len;
		char*	msg;

		for (;;)
		{
			if (safe_read(0, &msg_len, 4) != 4)
			{
				/* Erlang has closed the port, we should exit. */
				return 0;
			}

			/* Length comes in network byte order, must flip. */
			msg_len = ntohl(msg_len);
			msg = (char*)malloc(msg_len);

			if (safe_read(0, msg, msg_len) != msg_len)
			{
				/* Erlang has closed the port, we should exit. */
				return 0;
			}

			/* process message using ei like before */
			
			free(msg);
		}
	}

Note that when I say process the message you'll need to use ei_decode_*
to decode the message.  Start every message with ei_decode_version,
as every message will start off with the version number.

Sending is pretty much the same thing, just determine the total number
of bytes in the message, use htonl(x) to create the 4 byte length header
and send the header and the message.  Don't forget to use
ei_encode_version to add the version number to the start of any outbound
message, otherwise binary_to_term/1 will fail.


erlang@REDACTED wrote:
> I've got a program that acts as a C-Node written using the most
> excellent ei library.  This works very well, but in order to simplify
> startup I am investigating the use of a port instead.
> 
> Since I now have all this code making use of ei_xreceive_msg() and all
> those ei_decode_...() and ei_x_encode_...() functions, is there a way to
> write a port program, so that I can reuse most of this existing code?
> 
> In other words, how do I implement a port program that communicates
> with its parent using the external message format in such a way that I
> can use the ei library?

-- 
Shawn.



More information about the erlang-questions mailing list