-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnative.py
77 lines (69 loc) · 2.27 KB
/
native.py
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
################################################################
### A simple set of functions for embedding native C code
### inside Python.
################################################################
from __future__ import print_function
import os,hashlib
from ctypes import c_int,c_float,c_double,c_byte
from numpy.ctypeslib import ndpointer
import ctypes
import time
import errno
import contextlib
import platform
@contextlib.contextmanager
def lockfile(fname,delay=0.5):
while 1:
try:
fd = os.open(fname,os.O_RDWR|os.O_CREAT|os.O_EXCL)
except OSError as e:
if e.errno!=errno.EEXIST: raise
time.sleep(delay)
continue
else:
break
try:
yield fd
finally:
os.close(fd)
os.unlink(fname)
I = c_int
F = c_float
D = c_double
B = c_byte
for d in range(1,4):
for T,t in [("I","int32"),("F","float32"),("D","float64"),("B","int8"),("U","uint8")]:
exec "A%d%s = ndpointer(dtype='%s',ndim=%d,flags='CONTIGUOUS,ALIGNED')"%(d,T,t,d)
class CompileError(Exception):
pass
def compile_and_find(c_string,prefix=".pynative",opt="-g -O4",libs="-lm",
options="",verbose=0):
os_code = platform.platform()
#print("Checking platform----")
if "darwin" in str(os_code).lower():
options = "-shared -openmp -std=c99 -fPIC"
else:
options = "-shared -fopenmp -std=c99 -fPIC"
if not os.path.exists(prefix):
os.mkdir(prefix)
m = hashlib.md5()
m.update(c_string)
base = m.hexdigest()
if verbose: print("hash", base, "for", c_string[:20], "...")
with lockfile(os.path.join(prefix,base+".lock")):
so = os.path.join(prefix,base+".so")
if os.path.exists(so):
if verbose: print("returning existing", so)
return so
source = os.path.join(prefix,base+".c")
with open(source,"w") as stream:
stream.write(c_string)
cmd = "gcc "+opt+" "+libs+" "+options+" "+source+" -o "+so
if verbose: print("#", cmd)
if os.system(cmd)!=0:
if verbose: print("compilation failed")
raise CompileError()
return so
def compile_and_load(c_string,**keys):
path = compile_and_find(c_string,**keys)
return ctypes.CDLL(path)