diff --git a/Common/onelab.h b/Common/onelab.h index 6ad91635bcc1c830754ea3cf632ade8480a3d240..969fb629600c16ff92e6bdd87cdb9339ed11af93 100644 --- a/Common/onelab.h +++ b/Common/onelab.h @@ -702,7 +702,7 @@ namespace onelab{ const std::string &client=""){ return _set(p, client, _functions); } bool get(std::vector<number> &ps, const std::string &name="", const std::string &client=""){ return _get(ps, name, client, _numbers); } - bool get(std::vector<string> &ps, const std::string &name="", + bool get(std::vector<onelab::string> &ps, const std::string &name="", const std::string &client=""){ return _get(ps, name, client, _strings); } bool get(std::vector<region> &ps, const std::string &name="", const std::string &client=""){ return _get(ps, name, client, _regions); } @@ -817,7 +817,7 @@ namespace onelab{ virtual bool set(const region &p) = 0; virtual bool set(const function &p) = 0; virtual bool get(std::vector<number> &ps, const std::string &name="") = 0; - virtual bool get(std::vector<string> &ps, const std::string &name="") = 0; + virtual bool get(std::vector<onelab::string> &ps, const std::string &name="") = 0; virtual bool get(std::vector<region> &ps, const std::string &name="") = 0; virtual bool get(std::vector<function> &ps, const std::string &name="") = 0; std::vector<std::string> toChar() @@ -967,7 +967,7 @@ namespace onelab{ virtual bool set(const region &p){ return _set(p); } virtual bool get(std::vector<number> &ps, const std::string &name=""){ return _get(ps, name); } - virtual bool get(std::vector<string> &ps, + virtual bool get(std::vector<onelab::string> &ps, const std::string &name=""){ return _get(ps, name); } virtual bool get(std::vector<function> &ps, const std::string &name=""){ return _get(ps, name); } @@ -1005,8 +1005,10 @@ namespace onelab{ void setPid(int pid){ _pid = pid; } GmshServer *getGmshServer(){ return _gmshServer; } void setGmshServer(GmshServer *server){ _gmshServer = server; } + #ifndef SWIG virtual bool run(); virtual bool kill(); + #endif }; // The remote part of a network client. @@ -1112,7 +1114,7 @@ namespace onelab{ virtual bool set(const region &p){ return _set(p); } virtual bool get(std::vector<number> &ps, const std::string &name=""){ return _get(ps, name); } - virtual bool get(std::vector<string> &ps, + virtual bool get(std::vector<onelab::string> &ps, const std::string &name=""){ return _get(ps, name); } virtual bool get(std::vector<function> &ps, const std::string &name=""){ return _get(ps, name); } diff --git a/contrib/onelab/onelab.i b/contrib/onelab/onelab.i deleted file mode 100644 index ae601f09c8b1783f1d0545d74d720c86554c61a3..0000000000000000000000000000000000000000 --- a/contrib/onelab/onelab.i +++ /dev/null @@ -1,23 +0,0 @@ -%module onelab -%{ -#include "onelab.h" -onelab::server *onelab::server::_server = 0; -void modelName(const std::string &name, const std::string &wdir=""); -int metamodel(const std::string &todo); -void setNumber(const std::string &name, const double value); -void setString(const std::string &name, const std::string &value); -double getNumber(const std::string &name); -std::string getString(const std::string &name); - -%} - -%include std_string.i - -extern void modelName(const std::string &name, const std::string &wdir=""); -extern int metamodel(const std::string &todo); -extern void setNumber(const std::string &name, const double value); -extern void setString(const std::string &name, const std::string &value); -extern double getNumber(const std::string &name); -extern std::string getString(const std::string &name); - - diff --git a/contrib/onelab/python/OnelabClient.py b/contrib/onelab/python/OnelabClient.py new file mode 100755 index 0000000000000000000000000000000000000000..584c5f6dc4480a4daded0bc2991dd8004301bbcf --- /dev/null +++ b/contrib/onelab/python/OnelabClient.py @@ -0,0 +1,130 @@ +import socket, struct, os, sys +_VERSION = '1.05' + +class _parameter() : + _membersbase = [ + ('name', 'string'), ('label', 'string', ''), ('help', 'string', ''), + ('neverChanged', 'int', 0), ('changed', 'int', 1), ('visible', 'int', 1), + ('read_only', 'int', 0), ('attributes', ('dict', 'string', 'string'), {}), + ('clients', ('list', 'string'), []) + ] + _members = { + 'string' : _membersbase + [ + ('value', 'string'), ('kind', 'string', 'generic'), ('choices', ('list', 'string'), []) + ], + 'number' : _membersbase + [ + ('value', 'float'), ('min', 'float', -sys.float_info.max), ('max', 'float', sys.float_info.max), + ('step', 'float', 0.), ('index', 'int', -1), ('choices', ('list', 'float'), []), + ('labels', ('dict', 'float', 'string'), {}) + ] + } + + def __init__(self, type, **values) : + self.type = type + for i in _parameter._members[self.type] : + setattr(self, i[0], values[i[0]] if i[0] in values else i[2]) + + def tochar(self) : + def tocharitem(l, t, v) : + if t=='string' : l.append(v) + elif t =='int': l.append(str(v)) + elif t=='float' : l.append('%.16g' % v) + elif t[0]=='list' : + l.append(str(len(v))) + for i in v : tocharitem(l, t[1], i) + elif t[0]=='dict' : + l.append(str(len(v))) + for i, j in v.items() : + tocharitem(l, t[1], i) + tocharitem(l, t[2], j) + msg = [_VERSION, self.type] + for i in _parameter._members[self.type] : + tocharitem(msg, i[1], getattr(self, i[0])) + return '\0'.join(msg) + + def fromchar(self, msg) : + def fromcharitem(l, t) : + if t=='string' : return l.pop() + elif t =='int': return int(l.pop()) + elif t=='float' : return float(l.pop()) + elif t[0]=='list' : return [fromcharitem(l, t[1]) for i in range(int(l.pop()))] + elif t[0]=='dict' : return dict([(fromcharitem(l, t[1]),fromcharitem(l, t[2])) for i in range(int(l.pop()))]) + l = msg.split('\0') + l.reverse() + if l.pop() != _VERSION : + print('onelab version mismatch') + if l.pop() != self.type : + print('onelab parameter type mismatch') + for p in _parameter._members[self.type]: + setattr(self, p[0], fromcharitem(l, p[1])) + +class client : + _GMSH_START = 1 + _GMSH_STOP = 2 + _GMSH_INFO = 10 + _GMSH_PARAMETER = 23 + _GMSH_PARAMETER_QUERY = 24 + + def _receive(self) : + def buffered_receive(l) : + msg = b'' + while len(msg) < l: + chunk = self.socket.recv(l - len(msg)) + if not chunk : + RuntimeError('onelab socket closed') + msg += chunk + return msg + msg = buffered_receive(struct.calcsize('ii')) + t, l = struct.unpack('ii', msg) + msg = buffered_receive(l).decode('utf-8') + if t == self._GMSH_INFO : + print('onelab info : %s' % msg) + return t, msg + + def _send(self, t, msg) : + m = msg.encode('utf-8') + if self.socket.send(struct.pack('ii%is' %len(m), t, len(m), m)) == 0 : + RuntimeError('onelab socket closed') + + def _get_parameter(self, param) : + if not self.socket : + return + self._send(self._GMSH_PARAMETER_QUERY, param.tochar()) + (t, msg) = self._receive() + if t == self._GMSH_PARAMETER : + param.fromchar(msg) + elif t == self._GMSH_INFO : + self._send(self._GMSH_PARAMETER, param.tochar()) + + def get_string(self, name, value, **param): + param = _parameter('string', name=name, value=value, **param) + self._get_parameter(param) + return param.value + + def get_number(self, name, value, **param): + if "labels" in param : + param["choices"] = param["labels"].keys() + p = _parameter('number', name=name, value=value, **param) + self._get_parameter(p) + return p.value + + def __init__(self): + self.socket = None + self.name = "" + for i, v in enumerate(sys.argv) : + if v == '-onelab': + self.name = sys.argv[i + 1] + addr = sys.argv[2] + if '/' in addr or '\\' in addr or ':' not in addr : + self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + else : + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.connect(sys.argv[i + 2]) + self._send(self._GMSH_START, str(os.getpid)) + self.action = self.get_string(self.name + '/Action', 'compute') + if self.action == "initialize": exit(0) + + def __del__(self) : + if self.socket : + self._send(self._GMSH_STOP, 'Goodbye!') + self.socket.close() diff --git a/contrib/onelab/python/test.ol b/contrib/onelab/python/test.ol new file mode 100755 index 0000000000000000000000000000000000000000..79463f51e7665b85b585b2081d0a6d73a31ac3c8 --- /dev/null +++ b/contrib/onelab/python/test.ol @@ -0,0 +1,2 @@ +Native.register(native, ./test.py); +Native.run(); diff --git a/contrib/onelab/python/test.py b/contrib/onelab/python/test.py new file mode 100755 index 0000000000000000000000000000000000000000..631bb7070ff7213aa29e2017402ce0aa995d032a --- /dev/null +++ b/contrib/onelab/python/test.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +#coding=utf-8 +import OnelabClient + +oc = OnelabClient.client() + +#name and default value are required +A = oc.get_number('A', 10) +#other attributes are optionals +B = oc.get_number('Group/B', 0, min = -10, max = 10, step = 1) +C = oc.get_number('Group/C', 2, choices = [0, 1, 2, 3], attributes={'Highlight':'Pink'}) +D = oc.get_number('Group/D', 2, labels = {0:'zero', 1:'un', 2:'deux', 3:'trois'}, attributes={'Highlight':'Blue'}) +#utf-8 are allowed everywhere (should be prefixed by 'u' in python 2, not required in python 3) +Omega = oc.get_string(u'Ω', u'∫(∂φ/∂α)³dx', help=u'ask someone@universe.org', choices = ['oui', 'non', u'peut-être']) + +if oc.action != 'compute' : + exit(0) + +#this is the solver code +print (A, B, C, str(Omega)) diff --git a/contrib/onelab/python/wrappers/Makefile b/contrib/onelab/python/wrappers/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e3978894fe310ddf0256836c74d6f5efb4fde292 --- /dev/null +++ b/contrib/onelab/python/wrappers/Makefile @@ -0,0 +1,11 @@ +all: _onelab.so +GMSH_DIR=../../../../ +COMMON_DIR=$(GMSH_DIR)/Common +CPPFLAGS+= $(shell python-config --includes) -I$(COMMON_DIR) -DONELAB_LOADER + +onelab_wrap.cpp : onelab.i + swig -python -c++ ${CPPFLAGS} -o $@ $< + +_onelab.so : onelab_wrap.cpp + $(CXX) -shared onelab_wrap.cpp -o $@ $(CPPFLAGS) -fPIC -DSWIG +.PRECIOUS: $(OBJDIR)/%.o diff --git a/contrib/onelab/python/wrappers/OnelabClient.py b/contrib/onelab/python/wrappers/OnelabClient.py new file mode 100755 index 0000000000000000000000000000000000000000..6ec86419767f70e3e9e20dc275d4af438d99d540 --- /dev/null +++ b/contrib/onelab/python/wrappers/OnelabClient.py @@ -0,0 +1,58 @@ +import onelab +import sys + +class client : + + def get_number(self, name, default, label = '', min = -sys.float_info.max, max = sys.float_info.max, step = 0, choices = [], labels = [], attributes = {}, help = "", visible = 1, read_only = 0) : + if not self.client : + return default + n = onelab.number(name, default) + n.setLabel(label) + n.setVisible(visible) + n.setReadOnly(read_only) + n.setMin(min) + n.setMax(max) + n.setStep(step) + n.setHelp(help) + n.setChoices(choices) + if labels : + n.setChoices([k for k in labels.keys()]) + n.setChoiceLabels([v for v in labels.values()]) + for k,v in attributes.items() : + n.setAttribute(k, v) + r = onelab.OnelabNumberVector() + self.client.get(r, n.getName()) + if r : + return r[0].getValue() + else : + self.client.set(n) + return default + + def get_string(self, name, default, choices = [], help ="", label = "", visible = 1, read_only = 0, kind = "generic", attributes = {}) : + if not self.client : + return default + n = onelab.string(name, default) + n.setChoices(choices) + n.setReadOnly(read_only) + n.setVisible(visible) + n.setLabel(label) + n.setHelp(help) + n.setKind(kind) + r = onelab.OnelabStringVector() + for k,v in attributes.items() : + n.setAttribute(k, v) + self.client.get(r, n.getName()) + if r : + return r[0].getValue() + else : + self.client.set(n) + return default + + def __init__(self): + self.client = None + for i, v in enumerate(sys.argv) : + if v == '-onelab': + self.name = sys.argv[i + 1] + self.client = onelab.remoteNetworkClient(self.name, sys.argv[i+2]) + self.action = self.get_string(self.name + '/Action', 'compute') + if self.action == "initialize": exit(0) diff --git a/contrib/onelab/python/wrappers/onelab.i b/contrib/onelab/python/wrappers/onelab.i new file mode 100644 index 0000000000000000000000000000000000000000..21c18c2875c7f08846946dfea476cfb2058da243 --- /dev/null +++ b/contrib/onelab/python/wrappers/onelab.i @@ -0,0 +1,15 @@ +%module onelab +%{ +#include "onelab.h" +onelab::server *onelab::server::_server = 0; +%} + +%include std_string.i +%include std_vector.i +%include std_map.i +%template(OnelabNumberVector) std::vector<onelab::number>; +%template(OnelabStringVector) std::vector<onelab::string>; +%template(DoubleVector) std::vector<double>; +%template(StringVector) std::vector<std::string>; +%template(DoubleStringMap) std::map<double, std::string>; +%include "onelab.h" diff --git a/contrib/onelab/python/wrappers/test.ol b/contrib/onelab/python/wrappers/test.ol new file mode 120000 index 0000000000000000000000000000000000000000..200dd10d85efd84c095d81735c837aab44313a65 --- /dev/null +++ b/contrib/onelab/python/wrappers/test.ol @@ -0,0 +1 @@ +../test.ol \ No newline at end of file diff --git a/contrib/onelab/python/wrappers/test.py b/contrib/onelab/python/wrappers/test.py new file mode 120000 index 0000000000000000000000000000000000000000..40a41e7dea17bb7c99a4aaf88f309781c348d4bc --- /dev/null +++ b/contrib/onelab/python/wrappers/test.py @@ -0,0 +1 @@ +../test.py \ No newline at end of file