Guest User

Untitled

a guest
Jan 19th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.72 KB | None | 0 0
  1. local ffi = assert(require("ffi"))
  2. local PYTHON = assert(ffi.load("libpython3.5m.so", true))
  3.  
  4. ffi.cdef[[
  5. typedef void PyCompilerFlags;
  6. typedef struct _object {
  7. size_t ob_refcnt;
  8. struct _typeobject *ob_type;
  9. } PyObject;
  10.  
  11. // Types
  12. typedef struct _typeobject PyTypeObject;
  13. PyTypeObject _PyNone_Type;
  14. PyTypeObject PyLong_Type;
  15. PyTypeObject PyUnicode_Type;
  16. PyTypeObject PyFloat_Type;
  17.  
  18. // Initialization
  19. void Py_Initialize();
  20. void Py_Finalize();
  21. void PyErr_Print();
  22. PyObject * PyEval_GetBuiltins();
  23. void _Py_Dealloc(PyObject *);
  24.  
  25. // Dictionary functions
  26. PyObject * PyDict_New();
  27. PyObject * PyDict_GetItemString(PyObject *, const char *);
  28. int PyDict_SetItemString(PyObject *, const char *, PyObject *);
  29.  
  30. // Conversion
  31. long PyLong_AsLong(PyObject *);
  32. double PyFloat_AsDouble(PyObject *);
  33. PyObject* PyUnicode_AsASCIIString(PyObject *);
  34. char* PyBytes_AsString(PyObject *);
  35.  
  36. // Execution
  37. PyObject * PyRun_StringFlags(const char *, int, PyObject *, PyObject *, PyCompilerFlags *);
  38. ]]
  39.  
  40. local python_initialized = false
  41.  
  42. function Python()
  43. -- Initialize the Python interpreter (singleton)
  44. PYTHON.Py_Initialize()
  45. if python_initialized then
  46. error("There can only be one!")
  47. end
  48. python_initialized = true
  49.  
  50. -- Allocate a dictionary for locals and globals
  51. local locals = PYTHON.PyDict_New()
  52. local globals = PYTHON.PyDict_New()
  53.  
  54. -- Import builtins into global (otherwise things like "print" are missing)
  55. if (PYTHON.PyDict_GetItemString(globals, "__builtins__") == NULL) then
  56. if (PYTHON.PyDict_SetItemString(globals, "__builtins__",
  57. PYTHON.PyEval_GetBuiltins()) ~= 0) then
  58. error("Could not import builtins!")
  59. end
  60. end
  61.  
  62. -- Magic numbers
  63. local Py_file_input = 257
  64. local Py_eval_input = 258
  65.  
  66. -- XDECREF is a macro, thus we have to reimplement it
  67. local function Py_XDECREF(_py_decref_tmp)
  68. if _py_decref_tmp ~= nil then
  69. _py_decref_tmp.ob_refcnt = _py_decref_tmp.ob_refcnt - 1
  70. if _py_decref_tmp.ob_refcnt == 0 then
  71. PYTHON._Py_Dealloc(_py_decref_tmp)
  72. end
  73. end
  74. end
  75.  
  76. -- Evaluate a single statement and get the result
  77. local function get(expr)
  78. local r = PYTHON.PyRun_StringFlags(expr,Py_eval_input,globals,locals,nil)
  79.  
  80. local value = nil
  81.  
  82. if r == nil then
  83. -- Check for errors
  84. PYTHON.PyErr_Print()
  85. error("Python error!")
  86. else
  87. -- Convert last result
  88. if r.ob_type == PYTHON._PyNone_Type then
  89. value = nil
  90. elseif r.ob_type == PYTHON.PyLong_Type then
  91. value = tonumber(PYTHON.PyLong_AsLong(r))
  92. elseif r.ob_type == PYTHON.PyFloat_Type then
  93. value = tonumber(PYTHON.PyFloat_AsDouble(r))
  94. elseif r.ob_type == PYTHON.PyUnicode_Type then
  95. local pystr = PYTHON.PyUnicode_AsASCIIString(r)
  96. local str = PYTHON.PyBytes_AsString(pystr)
  97. value = ffi.string(str)
  98. Py_XDECREF(pystr)
  99. else
  100. error("Unknown type at " .. tostring(r.ob_type))
  101. end
  102. end
  103.  
  104. Py_XDECREF(r)
  105.  
  106. return value
  107. end
  108.  
  109. -- Evaluate a block of code (no return value)
  110. local function run(expr)
  111. local r = PYTHON.PyRun_StringFlags(expr,Py_file_input,globals,locals,nil)
  112. if r == nil then
  113. PYTHON.PyErr_Print()
  114. error("Python error!")
  115. end
  116. Py_XDECREF(r)
  117. end
  118.  
  119. -- Evaluate a block of code and retrieve whatever is stored in the
  120. -- variable "result"
  121. local function eval(expr)
  122. run(expr)
  123. return get"result"
  124. end
  125.  
  126. -- Register garbage collection in the finalizer
  127. local metatable = {
  128. __gc = function()
  129. Py_XDECREF(locals)
  130. Py_XDECREF(globals)
  131. PYTHON.Py_Finalize()
  132. end
  133. }
  134.  
  135. -- Export functions
  136. local instance = { run = run, get = get, eval = eval }
  137. setmetatable(instance, metatable)
  138. return instance
  139. end
  140.  
  141. --[[
  142.  
  143. To create a new Python interpreter, call Python(), which returns a
  144. table with functions. I'm not so sure about Python's memory
  145. management, that's why it is a singleton.
  146.  
  147. Available functions:
  148.  
  149. Python:get(string)
  150. Runs a single Python statement and returns the result as a Lua
  151. type. Supported types are None, Int, Float, String.
  152.  
  153. Python:run(string)
  154. Runs a block of Python code. Useful for defining functions or
  155. importing modules. Does not return a result.
  156.  
  157. Python:eval(string)
  158. Sort of combines the above. Runs a block of Python code and
  159. returns whatever has been stored in the variable "result". Will
  160. crash if "result" is not defined.
  161.  
  162. --]]
  163.  
  164. local python = Python()
  165.  
  166. python.run[[
  167. from scipy.integrate import quad
  168.  
  169. def integrand(x, a, b):
  170. return a*x**2 + b
  171. ]]
  172.  
  173. a = 2
  174. b = 1
  175. local v = python.get("quad(integrand, 0, 1, args=(" .. a .. "," .. b .. "))[0]")
  176. print(v)
Add Comment
Please, Sign In to add comment