在C ++中嵌入python,分段错误

时间:2016-08-03 14:09:02

标签: python c++ embedding

我想在c ++应用程序中嵌入python脚本。 为了尝试整合,我制作了一个试验代码:

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

我遇到了建议使用提升的帖子。 提升比这简单吗?简单明了:代码少,直接,主要由社区使用。

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

1 个答案:

答案 0 :(得分:-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;
}