The Lua, Perl, Python, and Ruby bindings use the same naming scheme as the C++ API in almost every case.
No attempt has been made to customize the API to the idioms of the respective scripting languages. This allows you to use the C++ API documentation for all environments. However, a few differences are forced upon the API by the languages. See the unit tests in tests/swig/lua
, tests/swig/perl
, tests/swig/python
, and tests/swig/ruby
for usage examples.
#include <ssrc/spread.h>
becomes require("ssrc.spread")
ssrc::spread::BaseMessage::SelfDiscard
becomes ssrc.spread.BaseMessage_SelfDiscard
.ssrc.spread.BaseMessage_SelfDiscard
instead of ssrc.spread.Message_SelfDiscard
ssrc::spread::BaseMessage::Reliable | ssrc::spread::BaseMessage::SelfDiscard
use ssrc.spread.BaseMessage_ReliableSelfDiscard
.pcall
. For example, the Lua unit tests do the following:
function test_error() local succeeded, message = pcall(mbox.join, mbox, "####"); assert(not succeeded) end
#include <ssrc/spread.h>
becomes use ssrc::spread;
$ssrc::spread::BaseMessage::SelfDiscard
instead of $ssrc::spread::Message::SelfDiscard
eval
, which makes the exception available via the $@
special variable. For example, the Perl unit tests do the following:
sub test_error { eval { $mbox->join("####"); }; is($@->error(), $ssrc::spread::Error::IllegalGroup); }
#include <ssrc/spread.h>
becomes import ssrc.spread
#include <ssrc/spread.h>
becomes require 'ssrc/spread'
private_name, proc_name = ssrc.spread.split_private_group("#foo#bar") private_name == "foo" # This expression evaluates to True proc_name == "bar" # This expression evaluates to TrueIn Lua split_private_group() returns a C++-style pair with .first and .second members, just like the C++ API.
g1 = ssrc.spread.GroupList() g2 = ssrc.spread.GroupList() g1.add("foo") g2.copy(g1) g2.group(0) == "foo" # This expression evaluates to True.
m = ssrc.spread.Message() m.write("foobar") m.rewind() s = m.read(m.size()) "foobar" == s # This expression evaluates to True.
readn
and writen
. Note, that readn
is dangerous (e.g., strings are supposed to be immutable in Python) and should be avoided unless you know exactly what you're doing.The Mailbox class uses the C++ idiom of resource acquisition is initialization. Therefore, no disconnect method is exposed and the disconnect happens in the destructor. In a garbage-collected scripting language, this means the disconnect may not happen at a predictable point when you stop using the object. You can invoke Mailbox::kill to free the file descriptor immediately, but don't continue to use the object afterward.
In order to specify a connection timeout, you may use the Timeout class or you may specify a timeout in seconds with a single integer. For example, to specify a connection timeout of 3 seconds in Python, you could use:
mbox = ssrc.spread.Mailbox("4803@localhost", "", True, ssrc.spread.Timeout(3));
or:
mbox = ssrc.spread.Mailbox("4803@localhost", "", True, 3);
You can't access the contents of a Message directly via &Message[0]
as in C++. Instead, you always have to read and write the contents using Message::read and Message::write. Because messages are treated as strings in the script environment, your data shouldn't contain null/0 characters. For example, if you write two strings to a message in a row and read them back into one string, you'll find that the result is treated as only the first string because of the null termination. For example:
m = ssrc.spread.Message() m.write("foo") m.write("bar") m.rewind() s = m.read(m.size()) "foo" == s # This expression evaluates to True. "foobar" == s # This expression evaluates to False. m.rewind() s1 = m.read(4) s2 = m.read(4) "foo" == s1 # This expression evaluates to True. "bar" == s2 # This expression evaluates to True.
As long as you use the script environment's object serialization mechanisms, you shouldn't run into any problems in this regard.
Don't add raw data parts (things that are not of type Message) to ScatterMessage::add or Mailbox::add_message_part if they will be garbage-collected before a send. For example:
s = "foo" mbox.add_message_part(s) s = None # Don't do this before the send or you may segfault! mbox.send()