Created
April 3, 2015 05:30
-
-
Save Synthetica9/bf8c30cbf2f34d50d034 to your computer and use it in GitHub Desktop.
for Joebo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__author__ = 'Synthetica' | |
from ctypes import * | |
import numpy as np | |
import itertools | |
import os | |
from inspect import getsourcefile | |
type_table = {1: c_bool, | |
2: c_char, | |
4: c_int, | |
8: c_double | |
} | |
_path = os.path.abspath(os.path.dirname(getsourcefile(lambda: None))) | |
if os.name == 'nt': | |
try: | |
std_lib = oledll.LoadLibrary(os.path.join(_path, 'j64.dll')) | |
except WindowsError: | |
std_lib = oledll.LoadLibrary(os.path.join(_path, 'j32.dll')) | |
elif os.name == 'posix': | |
std_lib = CDLL(os.path.join(_path, 'libj.so')) | |
else: | |
raise OSError('Unsupported os {o}'.format(repr(os.name))) | |
class JInstance(object): | |
def __init__(self, support_unix_pipe=True): | |
self.j_dll = std_lib | |
self.start_address = self.j_dll.JInit() | |
def __call__(self, command): | |
temp_name = 'TMP__' | |
type_name = 'TYPE__' | |
kind_name = 'KIND__' | |
error_name = 'ERROR__' | |
command = str(command) | |
#Delete all variables that are going to be used: | |
self.delete_var(temp_name, type_name, kind_name) | |
self.execute_command(command, temp_name, return_result=False) | |
return_type = self.execute_command( | |
"4!:0 < '{tmp}'".format(tmp=temp_name), type_name) | |
# Return the result, or raise an error: | |
if return_type == -2: | |
raise Exception("Invalid. That's all we know, sorry. " | |
"It would probably be wise to contact your " | |
"friendly neighbourhood library developer about " | |
"this error, because this shouldn't ever happen") | |
elif return_type == -1: | |
error_text = ''.join( | |
self.execute_command( | |
"(13 !: 12)''", | |
var_name=error_name | |
) | |
) | |
raise Exception("Undefined, an error probably " | |
"occurred somewhere along the way.\n" | |
"The last error raised:\n:" | |
"{t}".format(t=error_text)) | |
if return_type == 0: # Only nouns allowed. | |
# self.JGetM(temp_name, *data_pointers) | |
# return JRepr(*data_pointers) | |
return self.get_var(temp_name) | |
else: | |
raise TypeError( | |
"Impossible to return type {0}, must be 0.\n" | |
"(Piece of advice: are you trying to return a " | |
"verb/adverb/conjuction? Don't.)".format(return_type) | |
) | |
def __del__(self): | |
self.JFree() | |
def delete_var(self, *names): | |
if len(names) == 0: | |
return | |
elif len(names) == 1: | |
query = "4!:55 <'{name}'".format(name=names[0]) | |
else: | |
names = ["'{}'".format(name) for name in | |
names] # Surround with quotes | |
query = "4!:55 {names}".format(names='; '.join(names)) | |
self.execute_command(query) | |
def execute_command(self, command, var_name=None, return_result=True): | |
if var_name is not None: | |
self.set_var_raw(var_name, command) | |
if return_result: | |
return self.get_var(var_name) | |
else: | |
self.JDo(command) | |
if var_name is not None: | |
if return_result: | |
return self.get_var(var_name) | |
def set_var(self, name, value): | |
self.execute_command('{n} =: {v}'.format(n=name, v=pyToJ(value))) | |
def set_var_raw(self, name, value): | |
self.execute_command('{n} =: {v}'.format(n=name, v=value)) | |
def get_var(self, var_name): | |
pointers = [pointer(c_int()) for _ in range(4)] | |
self.JGetM(var_name, *pointers) | |
data = JRepr(*pointers) | |
return data | |
def __getattr__(self, item): | |
def wrapper(*args, **kwargs): | |
return getattr(self.j_dll, item)(self.start_address, *args, | |
**kwargs) | |
wrapper.__name__ = item | |
return wrapper | |
def JRepr(tpe, rnk, shp, pos, typelist=type_table): | |
tpe, rnk, shp, pos = (int(i.contents.value) for i in (tpe, rnk, shp, pos)) | |
shape = tuple(typelist[4].from_address(shp + i*sizeof(typelist[4])).value | |
for i in range(rnk)) | |
datalen = np.product(shape) if shape else 1 | |
ctype = typelist[tpe] | |
ctypesize = sizeof(ctype) | |
array = np.fromiter( | |
(ctype.from_address(pos + i*ctypesize).value | |
for i in itertools.count()), | |
dtype=ctype, | |
count=datalen | |
) | |
return np.resize(array, shape) | |
J = JInstance() | |
#Just for the console | |
def execute(command): | |
return J(command) | |
def debug(command): | |
return compile(command, '<string>', 'single')() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment