diff --git a/libqwqng-wrapper.so b/libqwqng-wrapper.so new file mode 100644 index 0000000..d1c01cf Binary files /dev/null and b/libqwqng-wrapper.so differ diff --git a/quanttp/__main__.py b/quanttp/__main__.py index cbaf2ae..2842c10 100644 --- a/quanttp/__main__.py +++ b/quanttp/__main__.py @@ -17,7 +17,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. - +import os import threading from flask import Flask, request, Response @@ -25,15 +25,14 @@ from flask_sockets import Sockets from gevent import pywsgi from geventwebsocket.handler import WebSocketHandler -from quanttp.data.qng_wrapper import QngWrapper -from quanttp.data.qng_wrapper_mock import QngWrapperMock +from quanttp.data.qng_wrapper_linux import QngWrapperLinux +from quanttp.data.qng_wrapper_windows import QngWrapperWindows app = Flask(__name__) sockets = Sockets(app) -qng_wrapper = QngWrapper() -# qng_wrapper = QngWrapperMock() +qng_wrapper = QngWrapperWindows() if (os.name == 'nt') else QngWrapperLinux() @app.route('/api/randint32') diff --git a/quanttp/data/qng_wrapper_linux.py b/quanttp/data/qng_wrapper_linux.py new file mode 100644 index 0000000..4333974 --- /dev/null +++ b/quanttp/data/qng_wrapper_linux.py @@ -0,0 +1,82 @@ +# Copyright (c) 2020 Andika Wasisto +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from ctypes import cdll, c_void_p, c_int, c_double, POINTER, c_char + + +class QngWrapperLinux: + + def __init__(self): + self.libqwqng_wrapper = cdll.LoadLibrary('./libqwqng-wrapper.so') + self.libqwqng_wrapper.GetQwqngInstance.restype = c_void_p + self.libqwqng_wrapper.RandInt32.argtypes = [c_void_p] + self.libqwqng_wrapper.RandInt32.restype = c_int + self.libqwqng_wrapper.RandUniform.argtypes = [c_void_p] + self.libqwqng_wrapper.RandUniform.restype = c_double + self.libqwqng_wrapper.RandNormal.argtypes = [c_void_p] + self.libqwqng_wrapper.RandNormal.restype = c_double + self.libqwqng_wrapper.RandBytes.argtypes = [c_void_p, c_int] + self.libqwqng_wrapper.RandBytes.restype = POINTER(c_char) + self.libqwqng_wrapper.Clear.argtypes = [c_void_p] + self.libqwqng_wrapper.Reset.argtypes = [c_void_p] + self.qng = self.libqwqng_wrapper.GetQwqngInstance() + + def randint32(self): + try: + return self.libqwqng_wrapper.RandInt32(self.qng) + except: + self.libqwqng_wrapper.Reset(self.qng) + return self.libqwqng_wrapper.RandInt32(self.qng) + + def randuniform(self): + try: + return self.libqwqng_wrapper.RandUniform(self.qng) + except: + self.libqwqng_wrapper.Reset(self.qng) + return self.libqwqng_wrapper.RandUniform(self.qng) + + def randnormal(self): + try: + return self.libqwqng_wrapper.RandNormal(self.qng) + except: + self.libqwqng_wrapper.Reset(self.qng) + return self.libqwqng_wrapper.RandNormal(self.qng) + + def randbytes(self, length): + try: + return self._randbytes_arbitrary_length(length) + except: + self.libqwqng_wrapper.Reset(self.qng) + return self._randbytes_arbitrary_length(length) + + def _randbytes_arbitrary_length(self, length): + if length <= 8192: + return self.libqwqng_wrapper.RandBytes(self.qng, length)[:length] + else: + data = bytearray() + for x in range(length // 8192): + data.extend(self.libqwqng_wrapper.RandBytes(self.qng, 8192)[:8192]) + bytes_needed = length % 8192 + if bytes_needed != 0: + data.extend(self.libqwqng_wrapper.RandBytes(self.qng, bytes_needed)[:bytes_needed]) + return bytes(data) + + def clear(self): + self.libqwqng_wrapper.Clear(self.qng) diff --git a/quanttp/data/qng_wrapper.py b/quanttp/data/qng_wrapper_windows.py similarity index 97% rename from quanttp/data/qng_wrapper.py rename to quanttp/data/qng_wrapper_windows.py index 80710e5..8618567 100644 --- a/quanttp/data/qng_wrapper.py +++ b/quanttp/data/qng_wrapper_windows.py @@ -18,12 +18,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import win32com.client - -class QngWrapper: +class QngWrapperWindows: def __init__(self): + import win32com.client self.qng = win32com.client.Dispatch("QWQNG.QNG") def randint32(self): diff --git a/requirements.txt b/requirements.txt index 850fa69..4f072ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ Flask==1.1.2 Flask-Sockets==0.2.1 gevent==20.5.0 gevent-websocket==0.10.1 -pywin32==227 \ No newline at end of file +pywin32==227; platform_system == 'Windows'