2

I have written a very simple C++ piece of code:

#include <iostream>
using namespace std;

int main() {

int message;

cin >> message;
cout << message;
return 0;
}

I have tested it in the shell - it returns a value which was input in the shell.

But when I try to call it from Erlang, it returns {exit_status,0}, which as I understand means that it just exited.

The Erlang code is here:

p(Param) ->
    ?DBG("Starting~n", []),
    Cmd = "./Echo\n",
    Port = open_port({spawn,Cmd}, [binary,{packet, 4},  exit_status]),
    Payload = term_to_binary(list_to_binary(integer_to_list(Param))),
    ?DBG("Opened the port: ~w~n", [Port]),
    erlang:port_command(Port, Payload),
    ?DBG("Sent command to port: ~w~n", [Payload]),
    ?DBG("Ready to receive results for command: ~w~n", [Payload]),
    receive
        {Port, {data, Data}} ->
            ?DBG("Received data: ~w~n", [Data]),
            {result, Text} = binary_to_term(Data),
            Blah = binary_to_list(Text),
            io:format("~p~n", [Blah]);
        Other ->
            io:format("Unexpected data: ~p~n", [Other])

    end.

How do I connect my Erlang port to this simple C++ code?

UPD:

Changed the C++ code to this (Useless' version):

#include <iostream>
using namespace std;

int main() {

int message;

cin.read(reinterpret_cast<char *>(&message), 4);
cout.write(reinterpret_cast<char *>(&message), 4);
return 0;
}

Erlang port process still gets {exit_value,0}. If I run this code in the shell, the keyboard input is not echoed until I press Return twice.

Mechanical snail
  • 29,755
  • 14
  • 88
  • 113
skanatek
  • 5,133
  • 3
  • 47
  • 75
  • 2
    Your question has nothing to do with C++. All you're looking for is how to connect the standard I/O files of a spawned process. – Kerrek SB Oct 18 '11 at 11:52
  • Could you please elaborate on this a bit more? Thanks! – skanatek Oct 18 '11 at 13:48
  • But with the second form you're waiting for 4 bytes from the terminal, eg. perhaps `\n\r` twice. I strongly suggest ditching the binary protocol on BOTH the Erlang and C++ sides, and just using text, unless you have a definite performance requirement. – Useless Oct 18 '11 at 14:19
  • Sorry I forgot to mention - performance is among my requirements. However, I don't know if using text will introduce an overhead: I need to pass about 30MB of data from Erlang to C++ and a few KB back from C++ to Erlang. So, maybe performance is not an issue with these amounts of data. Could you please help me with sending just text? – skanatek Oct 18 '11 at 14:39
  • If that's 30MB binary, formatting to text may well blow it up a bit. So, sticking with binary: can you write an Erlang replacement for the C++ code, and focus on getting your I/O working correctly before worrying about two languages? – Useless Oct 19 '11 at 13:43

3 Answers3

2

You know that the extraction operator cin >> expects formatted input, right? Which is to say, it would extract a string representing an integer, but probably won't deal well with a 4-byte binary integer or whatever that Erlang is sending.

If you want to read binary data, use

cin.read(reinterpret_cast<char *>(&message), 4);
cout.write(reinterpret_cast<char *>(&message), 4);

for example. Or, of course, write and receive text on the Erlang side.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • Sorry, I forgot to add a disclaimer: I am a C++ beginner. I have changed the 'cin >> message;' line to the one you provided, but I still get {exit_status,0} – skanatek Oct 18 '11 at 13:07
  • And the output side? The bottom line is, the insertion and extraction operator overloads for streams are generally used for formatted text, not binary data. I'll put the output side in my answer as well ... – Useless Oct 18 '11 at 13:14
  • Thanks! I have updated the question with the new code. Sorry for being such a C++ newbie - I can write very simple C++ programs only thanks to Java experience. – skanatek Oct 18 '11 at 13:53
1

With {packet, 4} Erlang adds and expects additional information for the following binaries. And, term_to_binary/1 encodes integer into BERT format (kind of a binary format like thrift). For an easy test you should use text protocol with parsing:

not: Payload = term_to_binary(list_to_binary(integer_to_list(Param))),

but: Payload = <<"hello, C++">>,

Cosmin
  • 21,216
  • 5
  • 45
  • 60
kuenishi
  • 11
  • 2
0

Maybe an acceptable workaround could be IPC? ZeroC has excellent C++ support and it would seem, decent Erlang support too.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173