Skip to content

Instantly share code, notes, and snippets.

@offlinehacker
Created October 30, 2014 22:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save offlinehacker/02a094ca2c88e20fcdf6 to your computer and use it in GitHub Desktop.
Save offlinehacker/02a094ca2c88e20fcdf6 to your computer and use it in GitHub Desktop.
Runs python from nix as a function (Run with: --option allow-unsafe-native-code-during-evaluation true)
{ runCommand, python, nix, boehmgc }:
let
eval-python-src = builtins.toFile "eval-python.cc" ''
#include <Python.h>
#include <eval.hh>
#include <gc/gc.h>
#include <gc/gc_cpp.h>
#define NEW new (UseGC)
using namespace std;
using namespace nix;
void prim_evalPython(EvalState& state, const Pos& pos, Value** args, Value& v) {
string catch_output =
"import sys\n\
class CatchOut:\n\
def __init__(self):\n\
self.value = \"\"\n\
def write(self, txt):\n\
self.value += txt\n\
catchOutErr = CatchOut()\n\
catchOut = CatchOut()\n\
sys.stdout = catchOut\n\
sys.stderr = catchOutErr\n\
"; //this is python code to redirect stdouts/stderr
PathSet context;
string code = state.coerceToString(pos, *args[0], context);
Py_Initialize();
PyObject *pModule = PyImport_AddModule("__main__");
PyRun_SimpleString(catch_output.c_str());
PyRun_SimpleString(code.c_str());
PyErr_Print();
PyObject *catcher = PyObject_GetAttrString(pModule, "catchOutErr");
PyObject *error = PyObject_GetAttrString(catcher, "value");
std::string error_s(PyString_AsString(error));
if (error_s.size()>0) throw EvalError(error_s);
catcher = PyObject_GetAttrString(pModule, "catchOut");
PyObject *output = PyObject_GetAttrString(catcher, "value");
string output_s(PyString_AsString(output));
mkString(v, output_s, PathSet());
Py_Finalize();
}
extern "C" void initialize(EvalState& state, Value& v) {
v.type = tPrimOp;
v.primOp = NEW PrimOp(prim_evalPython, 1, state.symbols.create("evalPython"));
}
'';
eval-python-so = runCommand "eval-python.so" {} ''
c++ -shared -fPIC -L${python}/lib/ -lpython2.7 -I${nix}/include/nix -I${boehmgc}/include -I${python}/include/python2.7/ -std=c++11 -O3 ${eval-python-src} -o $out
strip $out
'';
in builtins.importNative eval-python-so "initialize"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment