ferencd@0: #ifndef PYEMBED_H ferencd@0: #define PYEMBED_H ferencd@0: ferencd@0: // ferencd@0: // Copyright (C) 2011 Mateusz Loskot ferencd@0: // Distributed under the Boost Software License, Version 1.0. ferencd@0: // (See accompanying file LICENSE_1_0.txt or copy at ferencd@0: // http://www.boost.org/LICENSE_1_0.txt) ferencd@0: // ferencd@0: // Blog article: http://mateusz.loskot.net/?p=2819 ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: namespace emb ferencd@0: { ferencd@0: ferencd@0: typedef std::function stdout_write_type; ferencd@0: ferencd@0: struct Stdout ferencd@0: { ferencd@0: PyObject_HEAD ferencd@0: stdout_write_type write; ferencd@0: }; ferencd@0: ferencd@0: PyObject* Stdout_write(PyObject* self, PyObject* args) ferencd@0: { ferencd@0: std::size_t written(0); ferencd@0: Stdout* selfimpl = reinterpret_cast(self); ferencd@0: if (selfimpl->write) ferencd@0: { ferencd@0: char* data; ferencd@0: if (!PyArg_ParseTuple(args, "s", &data)) ferencd@0: return 0; ferencd@0: ferencd@0: std::string str(data); ferencd@0: selfimpl->write(str); ferencd@0: written = str.size(); ferencd@0: } ferencd@0: return PyLong_FromSize_t(written); ferencd@0: } ferencd@0: ferencd@0: PyObject* Stdout_flush(PyObject* /*self*/, PyObject* /*args*/) ferencd@0: { ferencd@0: // no-op ferencd@0: return Py_BuildValue(""); ferencd@0: } ferencd@0: ferencd@0: PyMethodDef Stdout_methods[] = ferencd@0: { ferencd@0: {"write", Stdout_write, METH_VARARGS, "sys.stdout.write"}, ferencd@0: {"flush", Stdout_flush, METH_VARARGS, "sys.stdout.write"}, ferencd@0: {0, 0, 0, 0} // sentinel ferencd@0: }; ferencd@0: ferencd@0: PyTypeObject StdoutType = ferencd@0: { ferencd@0: PyVarObject_HEAD_INIT(0, 0) ferencd@0: "emb.StdoutType", /* tp_name */ ferencd@0: sizeof(Stdout), /* tp_basicsize */ ferencd@0: 0, /* tp_itemsize */ ferencd@0: 0, /* tp_dealloc */ ferencd@0: 0, /* tp_print */ ferencd@0: 0, /* tp_getattr */ ferencd@0: 0, /* tp_setattr */ ferencd@0: 0, /* tp_reserved */ ferencd@0: 0, /* tp_repr */ ferencd@0: 0, /* tp_as_number */ ferencd@0: 0, /* tp_as_sequence */ ferencd@0: 0, /* tp_as_mapping */ ferencd@0: 0, /* tp_hash */ ferencd@0: 0, /* tp_call */ ferencd@0: 0, /* tp_str */ ferencd@0: 0, /* tp_getattro */ ferencd@0: 0, /* tp_setattro */ ferencd@0: 0, /* tp_as_buffer */ ferencd@0: Py_TPFLAGS_DEFAULT, /* tp_flags */ ferencd@0: "emb.Stdout objects", /* tp_doc */ ferencd@0: 0, /* tp_traverse */ ferencd@0: 0, /* tp_clear */ ferencd@0: 0, /* tp_richcompare */ ferencd@0: 0, /* tp_weaklistoffset */ ferencd@0: 0, /* tp_iter */ ferencd@0: 0, /* tp_iternext */ ferencd@0: Stdout_methods, /* tp_methods */ ferencd@0: 0, /* tp_members */ ferencd@0: 0, /* tp_getset */ ferencd@0: 0, /* tp_base */ ferencd@0: 0, /* tp_dict */ ferencd@0: 0, /* tp_descr_get */ ferencd@0: 0, /* tp_descr_set */ ferencd@0: 0, /* tp_dictoffset */ ferencd@0: 0, /* tp_init */ ferencd@0: 0, /* tp_alloc */ ferencd@0: 0, /* tp_new */ ferencd@0: }; ferencd@0: ferencd@0: #if PY_MAJOR_VERSION >= 3 ferencd@0: #define PY3K ferencd@0: #endif ferencd@0: ferencd@0: static PyModuleDef embmodule = ferencd@0: { ferencd@0: PyModuleDef_HEAD_INIT, ferencd@0: "emb", 0, -1, 0, ferencd@0: }; ferencd@0: ferencd@0: // Internal state ferencd@0: PyObject* g_stdout; ferencd@0: PyObject* g_stdout_saved; ferencd@0: ferencd@0: PyMODINIT_FUNC PyInit_emb(void) ferencd@0: { ferencd@0: g_stdout = 0; ferencd@0: g_stdout_saved = 0; ferencd@0: ferencd@0: StdoutType.tp_new = PyType_GenericNew; ferencd@0: if (PyType_Ready(&StdoutType) < 0) ferencd@0: return 0; ferencd@0: ferencd@0: PyObject* m = PyModule_Create(&embmodule); ferencd@0: if (m) ferencd@0: { ferencd@0: Py_INCREF(&StdoutType); ferencd@0: PyModule_AddObject(m, "Stdout", reinterpret_cast(&StdoutType)); ferencd@0: } ferencd@0: return m; ferencd@0: } ferencd@0: ferencd@0: void set_stdout(stdout_write_type write) ferencd@0: { ferencd@0: if (!g_stdout) ferencd@0: { ferencd@0: g_stdout_saved = PySys_GetObject("stdout"); // borrowed ferencd@0: g_stdout = StdoutType.tp_new(&StdoutType, 0, 0); ferencd@0: } ferencd@0: ferencd@0: Stdout* impl = reinterpret_cast(g_stdout); ferencd@0: impl->write = write; ferencd@0: PySys_SetObject("stdout", g_stdout); ferencd@0: } ferencd@0: ferencd@0: void reset_stdout() ferencd@0: { ferencd@0: if (g_stdout_saved) ferencd@0: PySys_SetObject("stdout", g_stdout_saved); ferencd@0: ferencd@0: Py_XDECREF(g_stdout); ferencd@0: g_stdout = 0; ferencd@0: } ferencd@0: ferencd@0: } // namespace emb ferencd@0: ferencd@0: #endif