Problem with porting ei program to MS Windows
pan+eq@REDACTED
pan+eq@REDACTED
Wed Apr 14 18:59:06 CEST 2004
Hi,
Rule of thumb, never use VC++ "unix/posix emulation thingie".
ReadFile and WriteFile are the Win32 calls for reading and witing to file
handles.
This makes the program work though (context diff):
*** crashtest.c.orig Wed Apr 14 18:52:41 2004
--- crashtest.c Wed Apr 14 18:53:48 2004
***************
*** 6,11 ****
--- 6,12 ----
#if defined(_WINDOWS)
# include <io.h>
+ # include <fcntl.h>
# include <winsock2.h>
#else
# include <unistd.h>
***************
*** 28,33 ****
--- 29,37 ----
{
ei_x_buff x;
+ #if defined(_WINDOWS)
+ _setmode(1,_O_BINARY);
+ #endif
logfile = fopen("LOGFILE", "w");
fprintf(logfile, "Started.\n");
Cheers,
/Patrik
On Wed, 14 Apr 2004 erlang@REDACTED wrote:
> Hi,
>
> I have a port program using the ei library running under Sparc Solaris.
> I have attemted porting it to Windows, but have come across the
> following problem. Most messages from my C program to Erlang cannot
> be correctly transformed with binary_to_term/1.
>
> I have reduced my program to something nice and small and have added
> debug output, and that shows identical streams of bytes being written.
> I am running R9C-0 on both Solaris and Windows XP.
>
> Any insights on this are happily received.
>
> Here is the run on Sparc Solaris:
> Eshell V5.3 (abort with ^G)
> 1> crashtest:start().
> <0.30.0>
> 2> {ok,[{section,name,[],[],[locked,expanded],user,0,unknown},
> {section,name,[],["one"],[],admin,1,bool},
> {section,name,[],["one","two"],[locked],internal,2,integer},
> {section,name,[],["one","two","three"],[expanded],deprecated,3,real},
> {section,name,[],["one","two","three","four"],[locked],user,4,string},
> {section,name,[],[],[],admin,5,enum},
> {section,name,[],["one"],[locked,expanded],internal,6,pathname},
> {section,name,[],["one","two"],[],deprecated,7,unknown},
> {section,name,[],["one","two","three"],[locked],user,8,bool},
> {section,name,[],["one","two","three","four"],[expanded],admin,9,integer},
> {section,name,[],[],[locked],internal,10,real},
> {section,name,[],["one"],[],deprecated,11,string},
> {section,name,[],["one","two"],[locked,expanded],user,12,enum},
> {section,name,[],["one","two","three"],[],admin,13,pathname}]}
> 2> ** exited: {port_terminated,{exit_status,0}} **
>
> But on Windows XP I get:
> Eshell V5.3 (abort with ^G)
> 1> crashtest:start().
> <0.30.0>
> 2>
> =ERROR REPORT==== 14-Apr-2004::17:18:33 ===
> Error in process <0.30.0> with exit value: {badarg,[{erlang,binary_to_term,[<<1145 bytes>>]},{crashtest,loop,1}]}
> 2> ** exited: {badarg,[{erlang,binary_to_term,
> [<<131,104,2,100,0,2,111,107,108,0,0,0,1,104,8,100,0,7,115,101,99,...>>]},
> {crashtest,loop,1}]} **
> 2>
>
> Here is crashtest.erl:
> -module(crashtest).
>
> -export([start/0, stop/0,init/1]).
>
> start() ->
> spawn_link(?MODULE, init, ["./crashtest"]).
>
> stop() ->
> myserver ! stop.
>
> init(Cmd) ->
> register(myserver, self()),
> process_flag(trap_exit, true),
> Port = open_port({spawn, Cmd}, [binary, {packet, 4}, exit_status]),
> loop(Port).
>
> loop(Port) ->
> receive
> {Port, {data, Data}} ->
> io:fwrite("~p~n", [binary_to_term(Data)]),
> loop(Port);
> stop ->
> port_close(Port),
> exit(normal);
> {Port, {exit_status, Status}} ->
> exit({port_terminated, {exit_status, Status}});
> {'EXIT', Port, Reason} ->
> exit({port_terminated, Reason})
> end.
>
>
> And here is crashtest.c:
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdarg.h>
> #include <ctype.h>
> #include <string.h>
>
> #if defined(_WINDOWS)
> # include <io.h>
> # include <winsock2.h>
> #else
> # include <unistd.h>
> # include <sys/types.h>
> # include <netinet/in.h>
> # include <inttypes.h>
> #endif
>
> #include "ei.h"
>
> /*support functions */
> static int safe_write(char* buf, int len);
> static int send_msg(ei_x_buff *x);
> static void build_message(ei_x_buff *x);
>
> FILE *logfile;
>
> int
> main(int argc, char **argv)
> {
> ei_x_buff x;
>
> logfile = fopen("LOGFILE", "w");
> fprintf(logfile, "Started.\n");
>
> ei_x_new(&x);
> build_message(&x);
> if (send_msg(&x) < 0)
> fprintf(logfile, "No port to Erlang!\n");
> ei_x_free(&x);
>
> return 0;
> }
>
> static int
> safe_write(char* buf, int len)
> {
> int tot = 0;
> int r;
>
> while (len > 0) {
> if ((r = write(1, buf, len)) <= 0)
> return r;
> tot += r;
> buf += r;
> len -= r;
> }
> return tot;
> }
>
> static void
> logbuff(char *b, int len, char *title)
> {
> int i;
>
> fprintf(logfile, "%s\n", title);
> for (i = 0; i < len; i++)
> {
> unsigned char c = b[i];
> fprintf(logfile, " %03u (%c)\n", c, isprint(c) ? c : ' ');
> }
> fprintf(logfile, "\n");
> }
>
> static int
> send_msg(ei_x_buff *x)
> {
> int host_len = x->index;
> int net_len = htonl(host_len);
>
> fprintf(logfile, "Sending %d bytes.\n", host_len);
>
> if (safe_write((char *) &net_len, 4) != 4)
> return -1;
>
> if (safe_write(x->buff, host_len) != host_len)
> return -1;
>
> logbuff(x->buff, host_len, "Sent:");
>
> return host_len;
> }
>
>
> static void
> encode_string_list(ei_x_buff *x, int n, char **strings)
> {
> int i;
>
> for (i = 0; i < n; i++) {
> ei_x_encode_list_header(x, 1);
> ei_x_encode_string(x, strings[i]);
> }
> ei_x_encode_empty_list(x);
> }
>
>
> static void
> build_message(ei_x_buff *x)
> {
> int i;
> int n = 14;
> static void build_elem(ei_x_buff *x, int i);
>
> /* {ok, [Elem]} */
> ei_x_encode_version(x);
> ei_x_encode_tuple_header(x, 2);
> ei_x_encode_atom(x, "ok");
> for (i = 0; i < n; i++) {
> ei_x_encode_list_header(x, 1);
> build_elem(x, i);
> }
> ei_x_encode_empty_list(x);
> }
>
> static void
> build_elem(ei_x_buff *x, int i)
> {
> /* {"section", "name", [sysvalues], [uservalues], [locked|expanded], Access,
> sig_count, Sig_type, [sig_enumerations]}
> where
> Access = user | admin | internal | deprecated
> Sig_type = unknown | bool | integer | real | string | enum | pathname
> */
>
> char *some_strings[] = { "one", "two", "three", "four", "five" };
> char *sig_access2str[] = { "user", "admin", "internal", "deprecated" };
> char *sig_type2str[] = { "unknown", "bool", "integer", "real", "string", "enum", "pathname" };
>
> ei_x_encode_tuple_header(x, 8);
> ei_x_encode_atom(x, "section"); /* 1 */
> ei_x_encode_atom(x, "name"); /* 2 */
> encode_string_list(x, 0, NULL); /* 3 */
> encode_string_list(x, i % 5, some_strings); /* 4 */
> if (i % 2 == 0) { /* 5 */
> ei_x_encode_list_header(x, 1);
> ei_x_encode_atom(x, "locked");
> }
> if (i % 3 == 0) {
> ei_x_encode_list_header(x, 1);
> ei_x_encode_atom(x, "expanded");
> }
> ei_x_encode_empty_list(x);
> ei_x_encode_atom(x, sig_access2str[i % 4]); /* 6 */
> ei_x_encode_long(x, i); /* 7 */
> ei_x_encode_atom(x, sig_type2str[i % 7]); /* 8 */
> }
>
>
> Thank you for any help,
> Robby
>
More information about the erlang-questions
mailing list