我有一个关于在c ++中嵌入python的完整示例。我在Linux上针对Python 2.7编译/链接它。
它需要一个参数(文件名),然后加载并执行。
这一切基本上都有效,但如果在代码中有: import shutils
然后执行代码失败并出现总线错误。
这似乎与潜在的“进口馆藏”有关。
当我将它作为python脚本执行时,我加载的代码正常运行。
是否有人提示为什么代码会崩溃?代码由几个示例组成,通常可以正常工作。
这是C ++代码:
#include "Python.h" // must be first
#include "structmember.h"
#include <stdio.h>
#include <stdlib.h>
#define QWE printf("%s %i\n", __FUNCTION__, __LINE__);
#define LIBPY_NAMESPACE "app"
#define LIBPY_TYPE "App"
#define LIBPY_FQTYPE LIBPY_NAMESPACE "." LIBPY_TYPE
static PyObject* globals;
static PyObject* locals;
static PyObject* mod;
static PyObject* app_class;
static PyObject* AppError;
typedef struct {
PyObject_HEAD
} AppObject;
static PyObject* app_func1(AppObject* self, PyObject* args)
{
PyObject* ret;
int p1, p2;
if(PyArg_ParseTuple(args, "dd", &p1, &p2)) {
// try {
ret = Py_BuildValue("(i,i,i,i)", 13, 17, 19, 11 + p1 + p2);
return ret;
/*
}
catch(RiException& e) {
PyErr_SetString(RiError, e.what());
}
*/
}
return NULL;
}
static PyObject* app_func2(AppObject* self, PyObject* args)
{
PyObject* ret;
ret = Py_BuildValue("(i,i,i,i)", 4, 13, 17, 19);
return ret;
}
static PyObject* app_filename(AppObject* self, PyObject* args)
{
PyObject* ret;
const char* c = "a filename";
// ret = Py_BuildValue("(i,i,i,i)", 4, 13, 17, 19);
ret = Py_BuildValue("s", c);
return ret;
}
static PyMethodDef app_global_methods[] = {
{"filename", (PyCFunction)app_filename, METH_VARARGS, "an example for a global function"},
// get file name
{NULL, NULL, 0, NULL}
};
static PyMethodDef app_methods[] = {
{"func1", (PyCFunction)app_func1, METH_VARARGS, "a test function 1."},
{"func2", (PyCFunction)app_func2, METH_NOARGS, "a test function 2."}
};
static PyMemberDef app_members[] = {
// {"width", T_INT, offsetof(RiMem, w), 0, ""},
{NULL}
};
static PyObject* app_repr(PyObject* par) {
AppObject* self = (AppObject*)par;
return PyString_FromFormat("<%s %i>", "wx Application", 4);
}
static PyObject* app_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
AppObject *self;
QWE;
self = (AppObject *)type->tp_alloc(type, 0);
if(self != NULL) {
// self->app = NULL;
}
return (PyObject *)self;
}
static int app_init(AppObject* self, PyObject* args, PyObject* kwds) {
// self->app = m_app;
QWE;
PyErr_Clear();
// PyErr_SetString(RiError, "some error happened");
return 0;
}
static void app_dealloc(AppObject* self) {
QWE;
/* if(self->app != NULL) {
// delete the app
self->app = NULL;
} */
self->ob_type->tp_free((PyObject*)self);
}
static PyTypeObject AppType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
LIBPY_FQTYPE, /*tp_name*/
sizeof(AppObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)app_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
app_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"An example application", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
app_methods, /* tp_methods */
app_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)app_init, /* tp_init */
0, /* tp_alloc */
app_new, /* tp_new */
};
void init_py(void) {
Py_SetProgramName("qwe");
Py_Initialize();
#if 0
globals = PyDict_New();
PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins());
#else
globals = PyModule_GetDict(PyImport_AddModule("__main__"));
#endif
printf("globals %p\n", globals);
/* if (PyType_Ready(&AppType) < 0) {
return;
} */
mod = Py_InitModule3(LIBPY_NAMESPACE, app_global_methods, "an example app module");
locals = PyModule_GetDict(mod);
Py_INCREF(&AppType);
PyModule_AddObject(mod, LIBPY_TYPE, (PyObject *)&AppType);
PyModule_AddIntConstant(mod, "CONST1", 11);
PyModule_AddIntConstant(mod, "CONST2", 13);
app_class = PyObject_GetAttrString(mod, LIBPY_TYPE);
AppError = PyErr_NewException((char*)LIBPY_FQTYPE "Error", NULL, NULL);
Py_INCREF(AppError);
PyModule_AddObject(mod, LIBPY_TYPE "Error", AppError);
// PyRun_SimpleString("from time import time,ctime\nprint 'Today is',ctime(time())\n");
// Py_Finalize();
}
char* load_file(const char* fname) {
FILE* fd;
long pos;
size_t len;
char* data;
fd = fopen(fname, "rb");
assert(fd != NULL);
fseek(fd, 0, SEEK_END);
pos = ftell(fd);
fseek(fd, 0, SEEK_SET);
data = (char*)malloc(pos+1);
assert(data != NULL);
len = fread(data, 1, pos, fd);
assert(len == (size_t)pos);
data[pos] = 0;
return data;
}
int main(int argc, char** argv) {
char* c;
PyObject* val;
printf("Hi there\n");
if(argc != 2) {
printf("need one parameter\n");
exit(-1);
}
init_py();
c = load_file(argv[1]);
printf("script <%s>\n", c);
QWE;
#if 1
PyRun_SimpleString(c);
#else
val = PyRun_String(c, Py_file_input, globals, locals);
QWE;
if(val == NULL) {
PyErr_Print();
}
else {
Py_DECREF(val);
}
#endif
QWE;
return 0;
}
失败的Python脚本是:
#! /usr/bin/python
#coding: latin-1
#from app import *
import os
import shutil
import sys
import stat
import fnmatch
import collections
#print filename()
因此,在编译代码然后使用参数(包含python代码的文件)调用代码时,会导致总线错误。
将上面的代码编译为C或C ++会得到相同的结果。我有兴趣让它与C ++一起使用。
至少有人可以重现这个问题吗?
答案 0 :(得分:0)
答案 1 :(得分:0)
我在上面的代码中发现了2个错误,其中一个是app_methods没有结束条目告诉python在哪里停止解释列表。
另一个是确实需要调用PyType_Ready(&amp; AppType)。我之前和之后使用过上面的代码(我认为使用Python 2.6)使用PyType_Ready()创建了一个总线错误。
编译代码时使用pythonx.y-config --cflags / --ldflags也很重要。