annotate templates/pyembed.h @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
rev   line source
ferencd@0 1 #ifndef PYEMBED_H
ferencd@0 2 #define PYEMBED_H
ferencd@0 3
ferencd@0 4 //
ferencd@0 5 // Copyright (C) 2011 Mateusz Loskot <mateusz@loskot.net>
ferencd@0 6 // Distributed under the Boost Software License, Version 1.0.
ferencd@0 7 // (See accompanying file LICENSE_1_0.txt or copy at
ferencd@0 8 // http://www.boost.org/LICENSE_1_0.txt)
ferencd@0 9 //
ferencd@0 10 // Blog article: http://mateusz.loskot.net/?p=2819
ferencd@0 11
ferencd@0 12 #include <functional>
ferencd@0 13 #include <iostream>
ferencd@0 14 #include <string>
ferencd@0 15 #include <Python.h>
ferencd@0 16
ferencd@0 17 namespace emb
ferencd@0 18 {
ferencd@0 19
ferencd@0 20 typedef std::function<void(std::string)> stdout_write_type;
ferencd@0 21
ferencd@0 22 struct Stdout
ferencd@0 23 {
ferencd@0 24 PyObject_HEAD
ferencd@0 25 stdout_write_type write;
ferencd@0 26 };
ferencd@0 27
ferencd@0 28 PyObject* Stdout_write(PyObject* self, PyObject* args)
ferencd@0 29 {
ferencd@0 30 std::size_t written(0);
ferencd@0 31 Stdout* selfimpl = reinterpret_cast<Stdout*>(self);
ferencd@0 32 if (selfimpl->write)
ferencd@0 33 {
ferencd@0 34 char* data;
ferencd@0 35 if (!PyArg_ParseTuple(args, "s", &data))
ferencd@0 36 return 0;
ferencd@0 37
ferencd@0 38 std::string str(data);
ferencd@0 39 selfimpl->write(str);
ferencd@0 40 written = str.size();
ferencd@0 41 }
ferencd@0 42 return PyLong_FromSize_t(written);
ferencd@0 43 }
ferencd@0 44
ferencd@0 45 PyObject* Stdout_flush(PyObject* /*self*/, PyObject* /*args*/)
ferencd@0 46 {
ferencd@0 47 // no-op
ferencd@0 48 return Py_BuildValue("");
ferencd@0 49 }
ferencd@0 50
ferencd@0 51 PyMethodDef Stdout_methods[] =
ferencd@0 52 {
ferencd@0 53 {"write", Stdout_write, METH_VARARGS, "sys.stdout.write"},
ferencd@0 54 {"flush", Stdout_flush, METH_VARARGS, "sys.stdout.write"},
ferencd@0 55 {0, 0, 0, 0} // sentinel
ferencd@0 56 };
ferencd@0 57
ferencd@0 58 PyTypeObject StdoutType =
ferencd@0 59 {
ferencd@0 60 PyVarObject_HEAD_INIT(0, 0)
ferencd@0 61 "emb.StdoutType", /* tp_name */
ferencd@0 62 sizeof(Stdout), /* tp_basicsize */
ferencd@0 63 0, /* tp_itemsize */
ferencd@0 64 0, /* tp_dealloc */
ferencd@0 65 0, /* tp_print */
ferencd@0 66 0, /* tp_getattr */
ferencd@0 67 0, /* tp_setattr */
ferencd@0 68 0, /* tp_reserved */
ferencd@0 69 0, /* tp_repr */
ferencd@0 70 0, /* tp_as_number */
ferencd@0 71 0, /* tp_as_sequence */
ferencd@0 72 0, /* tp_as_mapping */
ferencd@0 73 0, /* tp_hash */
ferencd@0 74 0, /* tp_call */
ferencd@0 75 0, /* tp_str */
ferencd@0 76 0, /* tp_getattro */
ferencd@0 77 0, /* tp_setattro */
ferencd@0 78 0, /* tp_as_buffer */
ferencd@0 79 Py_TPFLAGS_DEFAULT, /* tp_flags */
ferencd@0 80 "emb.Stdout objects", /* tp_doc */
ferencd@0 81 0, /* tp_traverse */
ferencd@0 82 0, /* tp_clear */
ferencd@0 83 0, /* tp_richcompare */
ferencd@0 84 0, /* tp_weaklistoffset */
ferencd@0 85 0, /* tp_iter */
ferencd@0 86 0, /* tp_iternext */
ferencd@0 87 Stdout_methods, /* tp_methods */
ferencd@0 88 0, /* tp_members */
ferencd@0 89 0, /* tp_getset */
ferencd@0 90 0, /* tp_base */
ferencd@0 91 0, /* tp_dict */
ferencd@0 92 0, /* tp_descr_get */
ferencd@0 93 0, /* tp_descr_set */
ferencd@0 94 0, /* tp_dictoffset */
ferencd@0 95 0, /* tp_init */
ferencd@0 96 0, /* tp_alloc */
ferencd@0 97 0, /* tp_new */
ferencd@0 98 };
ferencd@0 99
ferencd@0 100 #if PY_MAJOR_VERSION >= 3
ferencd@0 101 #define PY3K
ferencd@0 102 #endif
ferencd@0 103
ferencd@0 104 static PyModuleDef embmodule =
ferencd@0 105 {
ferencd@0 106 PyModuleDef_HEAD_INIT,
ferencd@0 107 "emb", 0, -1, 0,
ferencd@0 108 };
ferencd@0 109
ferencd@0 110 // Internal state
ferencd@0 111 PyObject* g_stdout;
ferencd@0 112 PyObject* g_stdout_saved;
ferencd@0 113
ferencd@0 114 PyMODINIT_FUNC PyInit_emb(void)
ferencd@0 115 {
ferencd@0 116 g_stdout = 0;
ferencd@0 117 g_stdout_saved = 0;
ferencd@0 118
ferencd@0 119 StdoutType.tp_new = PyType_GenericNew;
ferencd@0 120 if (PyType_Ready(&StdoutType) < 0)
ferencd@0 121 return 0;
ferencd@0 122
ferencd@0 123 PyObject* m = PyModule_Create(&embmodule);
ferencd@0 124 if (m)
ferencd@0 125 {
ferencd@0 126 Py_INCREF(&StdoutType);
ferencd@0 127 PyModule_AddObject(m, "Stdout", reinterpret_cast<PyObject*>(&StdoutType));
ferencd@0 128 }
ferencd@0 129 return m;
ferencd@0 130 }
ferencd@0 131
ferencd@0 132 void set_stdout(stdout_write_type write)
ferencd@0 133 {
ferencd@0 134 if (!g_stdout)
ferencd@0 135 {
ferencd@0 136 g_stdout_saved = PySys_GetObject("stdout"); // borrowed
ferencd@0 137 g_stdout = StdoutType.tp_new(&StdoutType, 0, 0);
ferencd@0 138 }
ferencd@0 139
ferencd@0 140 Stdout* impl = reinterpret_cast<Stdout*>(g_stdout);
ferencd@0 141 impl->write = write;
ferencd@0 142 PySys_SetObject("stdout", g_stdout);
ferencd@0 143 }
ferencd@0 144
ferencd@0 145 void reset_stdout()
ferencd@0 146 {
ferencd@0 147 if (g_stdout_saved)
ferencd@0 148 PySys_SetObject("stdout", g_stdout_saved);
ferencd@0 149
ferencd@0 150 Py_XDECREF(g_stdout);
ferencd@0 151 g_stdout = 0;
ferencd@0 152 }
ferencd@0 153
ferencd@0 154 } // namespace emb
ferencd@0 155
ferencd@0 156 #endif