【问题标题】:Embedding python in C++, Segmentation fault在 C++ 中嵌入 python,分段错误
【发布时间】:2016-08-03 14:09:02
【问题描述】:

我正在尝试将 python 脚本嵌入到 c++ 应用程序中。 为了尝试集成,我做了一个试验代码:

// c++ code

int main(int argc, char *argv[])
{
    PyObject *pName, *pModule, *pDict, *pFunc, *pValue;

    if (argc < 3) 
    {
        printf("Usage: exe_name python_source function_name\n");
        return 1;
    }

    // Initialize the Python Interpreter
    Py_Initialize();

    // Build the name object
    pName = PyBytes_FromString(argv[1]);
    //std::to_string(argv[1]).encode(

    // Load the module object
    pModule = PyImport_Import(pName);

    // pDict is a borrowed reference 
    pDict = PyModule_GetDict(pModule);

    // pFunc is also a borrowed reference 
    pFunc = PyDict_GetItemString(pDict, argv[2]);

    if (PyCallable_Check(pFunc)) 
    {
        PyObject_CallObject(pFunc, NULL);
    } 
    else 
    {
        PyErr_Print();
    }

    // Clean up
    Py_DECREF(pModule);
    Py_DECREF(pName);

    // Finish the Python Interpreter
    Py_Finalize();

    return 0;
}


# Python script
def multiply():
    c = 12345*6789
    print ('The result of 12345 x 6789 :' + str(c))

我遇到了建议使用 boost 的帖子。 提升比这更简单吗?简单的定义:更少的代码,直接的,被社区广泛使用。

我对这些问题很感兴趣,因为我们要集成的真实代码非常复杂(因为不遵循编码伦理),并且它需要与 Python 代码多次通信,因此也存在同步问题。

【问题讨论】:

  • 崩溃发生在哪里?你如何调用你的程序(即你传递给它的参数是什么)?您的实际代码中是否有任何空指针检查?
  • 代码在 `pFunc = PyDict_GetItemString(pDict, argv[2]);` 行崩溃;是的,正在检查指针是否为空,直到 pDict 的每个人都不为空。我这样称呼它:./test_cpp.o test_python multiply test_python 是 python 脚本的名称
  • 崩溃的调用栈是直接指向这一行,还是python内部的某个地方?坠机的具体情况是什么?
  • 本题C++内容不多,c标签可能更合适。

标签: python c++ embedding


【解决方案1】:

使用boost::python 或cython 生成的代码可能更容易。

罪魁祸首似乎是失踪了

PySys_SetArgv(argc, wargs);

其中wargs 包含作为宽字符串的参数。没有它,相对导入将不起作用。

以下代码(使用 gcc 编译,g++ 在malloc() 的情况下需要一些强制转换)似乎可以工作。

#include <Python.h>
#include <string.h>

int to_wide_args(wchar_t **argsw[], int argc, char *argv[])
{
    int i;
    size_t len;
    wchar_t *wstr;
    wchar_t **tmp = NULL;
    tmp = malloc(sizeof(wchar_t **) * argc);

    for (i = 0; i < argc; i++) {
        /* In case of python 3.5, see Py_DecodeLocale */
        len = mbstowcs(NULL, argv[i], 0);
        wstr = malloc(sizeof(wchar_t) * (len + 1));
        if (len != mbstowcs(wstr, argv[i], len + 1)) {
            return -1;
        }
        tmp[i] = wstr;
    }
    *argsw = tmp;
    return 0;
}

int main(int argc, char *argv[])
{
    PyObject *dict = 0;
    PyObject *func = 0;
    PyObject *module = 0;

    wchar_t **wargs = NULL;
    int rc = 0;

    if (argc < 3) {
        printf("Usage: exe_name python_source function_name\n");
        return 1;
    }

    if (to_wide_args(&wargs, argc, argv) < 0) goto error;

    Py_SetProgramName(wargs[0]);
    Py_Initialize();
    PySys_SetArgv(argc, wargs);

    if (PyErr_Occurred()) goto error;

    module = PyImport_ImportModule(argv[1]);
    printf("Module ptr: %p\n", module);
    if (module == NULL || PyErr_Occurred()) goto error;

    dict = PyModule_GetDict(module);
    printf("Module dict ptr: %p\n", dict);
    if (dict == NULL || PyErr_Occurred()) goto error;

    func = PyDict_GetItemString(dict, argv[2]);
    printf("Function ptr: %p\n", func);
    if (func == NULL || PyErr_Occurred()) goto error;

    if (PyCallable_Check(func)) {
        PyObject_CallObject(func, NULL);
    } else {
        goto error;
    }
    goto ok;

error:
    PyErr_Print();
    rc = 1;
ok:
    Py_XDECREF(module);
    Py_Finalize();

    return rc;
}

【讨论】:

    猜你喜欢
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 2017-05-26
    • 1970-01-01
    相关资源
    最近更新 更多