I’m using the following C function to run Python inside a C++ program.
INLINE int pyo_exec_statement(PyThreadState *interp, char *msg, int debug) {
int err = 0;
if (debug) {
PyObject *module, *obj;
char pp[26] = "_error_=None\ntry:\n ";
char tab[5] = " ";
char *starting_pos = msg;
size_t num_newlines, i, j = 0;
size_t *newlines_ndxs;
memmove(msg + strlen(pp), msg, strlen(msg)+1);
memmove(msg, pp, strlen(pp));
strcat(msg, "\nexcept Exception as _e_:\n _error_=str(_e_)");
/* find number of newline characters in the string */
for (i = 0; msg[i]; msg[i] == '\n' ? i++ : *msg++);
num_newlines = i;
/* reset the msg pointer to its starting position */
msg = starting_pos;
/* allocate memory for the array that will hold the indexes of the newline characters */
newlines_ndxs = (size_t*)malloc(sizeof(size_t) * num_newlines);
for (i = 0; msg[i] != '\0'; i++) {
if (msg[i] == '\n') {
newlines_ndxs[j++] = i+1;
}
}
/* we ignore the last two newlines and the first two
we loop in reverse so the newlines indexes don't chage as we insert tabs
*/
for (i = num_newlines-3; i > 1; i--) {
insertStringInPlace(msg, tab, newlines_ndxs[i]);
}
PyEval_AcquireThread(interp);
err = PyRun_SimpleString(msg);
module = PyImport_AddModule("__main__");
if (module != NULL) {
obj = PyObject_GetAttrString(module, "_error_");
if (obj != Py_None && obj != NULL) {
if (PyUnicode_AsUTF8(obj) != NULL) {
strcpy(msg, PyUnicode_AsUTF8(obj));
}
err = 1;
}
}
PyEval_ReleaseThread(interp);
}
else {
PyEval_AcquireThread(interp);
err = PyRun_SimpleString(msg);
PyEval_ReleaseThread(interp);
}
return err;
}
It runs fine and I get the traceback in my C++ program (copied to the msg char array) when executing single lines. When I execute more than one line though, it does execute fine, but I don’t get the proper traceback.
For example, if I try to execute the following:
def foo():
print("bar")
for i in range(10):
print(i)
The code obviously doens’t run because of the indentation error, but inside the C++ program, the chunk of code above, wrapped in a try/except structure is copied to the msg char array, while in the terminal I get the traceback, which, in the case above is:
File "<string>", line 5
for i in range(10):
IndentationError: unexpected indent
How can I get the traceback above in my C/C++ code?