|
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
|