Last active
March 13, 2021 11:27
-
-
Save jserv/11d02a2ba126f4056aae5b43ce9fa51f to your computer and use it in GitHub Desktop.
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
import atexit | |
import ctypes | |
import os | |
import shlex | |
import sys | |
import tempfile | |
CMD_C_TO_SO = '{compiler} -shared -o {output} {input} {libraries}' | |
class C: | |
def __init__(self, code, *shared_libs): | |
self.library = None | |
self._compile(code, shared_libs) | |
def _compile(self, code, libs): | |
# Dump the C code into a temporary file, and run the compiler | |
with tempfile.NamedTemporaryFile(mode='w', prefix='PYC', suffix='.c', | |
delete=False) as temp_c_file: | |
temp_c_file_name = temp_c_file.name | |
temp_c_file.write(code) | |
temp_c_file.flush() | |
# Run the compiler one more time to generate a shared library | |
so_file_name = tempfile.mktemp(prefix='PYC', suffix='.so') | |
library_cmd = ' '.join('-l' + lib for lib in libs) | |
os.system(CMD_C_TO_SO.format(compiler="gcc", | |
output=shlex.quote(so_file_name), | |
input=shlex.quote(temp_c_file_name), | |
libraries=library_cmd)) | |
# Punt to ctypes so that we can get a loadable library we built | |
self.library = ctypes.cdll.LoadLibrary(so_file_name) | |
# Ensure that we clean up the temp files when the program is exiting | |
atexit.register(lambda: os.remove(so_file_name)) | |
def __getitem__(self, func): | |
if self.library is None: | |
assert False, "How did C.__getitem__ get called without loading the library?" | |
return getattr(self.library, func) | |
if __name__ == '__main__': | |
mylib = C(''' | |
int factorial(int x) { | |
int ret = 1; | |
for (; x > 1; x--) | |
ret *= x; | |
return ret; | |
} | |
''') | |
factorial = mylib['factorial'] | |
print('15! =', factorial(15)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment