forked from vitillo/python-yampl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
yampl.pyx
118 lines (98 loc) · 2.93 KB
/
yampl.pyx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
from libc.stdlib cimport malloc, free
from libcpp.string cimport string
from cython.operator cimport dereference as dereference
import pickle
cdef extern from "Python.h":
char* PyBytes_AsString(object string)
object PyBytes_FromStringAndSize(const char *, Py_ssize_t)
cdef extern from "Channel.h" namespace "yampl":
cdef enum Context:
THREAD = 0,
LOCAL_SHM,
LOCAL_PIPE,
LOCAL,
DISTRIBUTED
cdef cppclass Channel:
string name
Context context
Channel(const string&, Context)
cdef extern from "ISocket.h" namespace "yampl":
cdef cppclass ISocket:
void send(void *, size_t) except +
size_t recv(void *&buffer) except +
ssize_t tryRecv(void *&buffer, long timeout) except +
cdef extern from "SocketFactory.h" namespace "yampl":
cdef cppclass SocketFactory:
ISocket *createClientSocket(Channel channel)
ISocket *createServerSocket(Channel)
cdef class PySocket:
cdef ISocket *socket
cdef SocketFactory *factory
cdef Channel *channel
def __cinit__(self, name, context):
self.socket = self.factory = self.channel = NULL
decoded = name.encode("utf-8")
cdef string *n = new string(<char*>decoded)
cdef Context c
context = context.upper()
if context == "THREAD":
c = THREAD
elif context == "LOCAL_SHM":
c = LOCAL_SHM
elif context == "LOCAL_PIPE":
c = LOCAL_PIPE
elif context == "LOCAL":
c = LOCAL
elif context == "DISTRIBUTED":
c = DISTRIBUTED
else:
raise NameError(context + " is not a valid contex")
self.channel = new Channel(dereference(n), c)
self.factory = new SocketFactory()
del n
def __dealloc__(self):
del self.socket
del self.channel
del self.factory
def send(self, message):
pickled = pickle.dumps(message)
self.socket.send(PyBytes_AsString(pickled), len(pickled));
def send_raw(self, message):
cdef char *msg = message
self.socket.send(msg, len(message))
def recv(self):
cdef char *msg = NULL
size = self.socket.recv(msg)
obj = pickle.loads(PyBytes_FromStringAndSize(msg, size));
free(msg)
return (size, obj)
def try_recv(self, timeout=0):
cdef char *msg = NULL
size = self.socket.tryRecv(msg, timeout)
obj = ''
if size != -1:
obj = pickle.loads(PyBytes_FromStringAndSize(msg, size));
free(msg)
return (size, obj)
def recv_raw(self):
cdef char *msg = NULL
size = self.socket.recv(msg)
obj = PyBytes_FromStringAndSize(msg, size)
free(msg)
return (size, obj)
def try_recv_raw(self, timeout=0):
cdef char *msg = NULL
size = self.socket.tryRecv(msg, timeout)
obj = ''
if size != -1:
obj = PyBytes_FromStringAndSize(msg, size)
free(msg)
return (size, obj)
cdef class ClientSocket(PySocket):
def __cinit__(self, name, context):
super().__init__(self, name, context)
self.socket = self.factory.createClientSocket(dereference(self.channel))
cdef class ServerSocket(PySocket):
def __cinit__(self, name, context):
super().__init__(self, name, context)
self.socket = self.factory.createServerSocket(dereference(self.channel))