2016-09-03 4 views
0

私は以下のC++でpythonを埋め込んだ完全な例を持っています。 Linux上でPython 2.7に対してコンパイル/リンクします。PythonをC++に埋め込み、 "import shutil"でクラッシュする

1つのパラメータ(ファイル名)が読み込まれ、実行されます。

すべてこれは基本的に動作しますが、コード内に存在する場合: インポート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; 
} 

A 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

CまたはC++?一つを選ぶ。 – Biffen

+0

テキストの見出しと最初の文で説明したように、C++です。それとも私はあなたの意見を誤解しましたか? –

+0

だから、「* Cコードは?」の後にCコードが続きますか? – Biffen

答えて

0

が、それはGILの問題に関連してもよいし、これを試してみてください。

+0

他のスレッドは使用しません。また、pythonコードの実行(PyRun_String)はmain()で一度しか呼び出されません。私はそれがスレッドに関連しているとは思わない。 –

0

https://docs.python.org/3/c-api/init.html#non-python-created-threadsは、私は上記の私のコードでは2のエラーを発見した、一つはapp_methodsリストを解釈停止するのpythonを伝える終わりエントリを持っていないということです。

PyType_Ready(& AppType)を呼び出すことが本当に必要であるということです。 PyType_Ready()を使用してバスエラーを作成していましたが、私は前と後のコードを使用しました(私はPython 2.6と思う)。

コードのコンパイル時にpythonx.y-config --cflags/--ldflagsを使用することも重要です。