import sys, os, struct, traceback from cStringIO import StringIO class ErlangPort(object): PACK = '!h' def __init__(self): self._in = sys.stdin self._out = sys.stdout def recv(self): buf = self._in.read(2) if len(buf) ==2: (sz,) = struct.unpack(self.PACK, buf) return self._in.read(sz) def send(self, what): sz = len(what) buf = struct.pack(self.PACK, sz) self._out.write(buf) return self._out.write(what) def run(self): buf = self.recv() while buf: try: result = self.process(buf) except: result = traceback.format_exc() self.send(result) buf = self.recv() class ErlangPortTest(ErlangPort): cmds = (0,lambda x: x+2, lambda x: x*2) def process(self, message): fn,arg = struct.unpack('!BB', message) res = self.cmds[fn](arg) return struct.pack('!B', res) class ErlangPyTest(ErlangPortTest): class SandBox: def process(self, message): exec message sandbox = SandBox() def process(self, code): try: realout = sys.stdout sys.stdout = StringIO() self.sandbox.process(code) result = sys.stdout.getvalue() finally: if sys.stdout: sys.stdout.close() if realout: sys.stdout = realout return result if __name__ =='__main__': import sys try: command = sys.argv[1] if command == 'PortTest': ErlangPortTest().run() elif command =='pytest': ErlangPyTest().run() except IndexError: print """ Usage: First of all see the c Port section in the Erlang guide. http://www.erlang.org/doc/tutorial/c_port.html#4 1. Start Erlang and compile the Erlang user guide example code: http://www.erlang.org/doc/tutorial/complex1.erl unix> erl Erlang (BEAM) emulator version 4.9.1.2 Eshell V4.9.1.2 (abort with ^G) 1> c(complex1). {ok,complex1} 3. Run the example. 2> complex1:start("python -u port.py PortTest"). <0.34.0> 3> complex1:foo(3). 4 4> complex1:bar(5). 10 5> complex1:stop(). stop For more fun try. 6> c("c:\\tg\\python.erl"). :/tg/python.erl:42: Warning: variable 'Reason' is unused {ok,python} 7> python:start("c:\\python25\\python.exe -u c:\\tg\\port.py pytest"). <0.38.0> 8> python:exec("import os") 9> python:exec("self.x = os.environ['PATH']"). * 2: syntax error before: python ** 10> python:exec("import os"). [] 11> python:exec("self.x = os.environ['PATH']"). [] 12> python:exec("print self.x"). "H:\\PROGRA~1\\ERL55~1.5\\ERTS-5~1.5\\bin;H:\\PROGRA~1\\ERL55~1.5\\bin m Files\\ActivePositionManager\\;C:\\WINNT\\system32;C:\\WINNT;C:\\WI 32\\Wbem;" """