首页 > 解决方案 > 即使 _DEBUG 未定义,嵌入式 Python 仍在寻找调试符号

问题描述

我正在尝试将 Python 嵌入到 C++ 应用程序中,并且我需要它作为发布版本运行,因为我只对调试 C++ 代码感兴趣。另外,我没有_d我需要的所有库的调试版本。我正在使用 Python 3.7.0,在带有 C++11 的 MSVC 2017 中,我没有调试符号的库是 VTK,我通过雇主提供的轮子文件安装了它。如果我尝试自己构建 Python 包装器,我会遇到另一个问题,因此我无法构建调试文件。如果我在调试模式下运行,我无法导入库,而如果我在发布模式下运行,我会遇到更多问题:

Exception thrown at 0x00007FF90841DBC9 (python37_d.dll) in PythonEmbedding.exe: 0xC0000005: Access violation reading location 0x0000000000000025.

C++ 代码:

int main(int argc, char *argv[])
{
    PyObject *pIntrospector = NULL;

    if (PyVtk_InitIntrospector(pIntrospector) == OK)
    {
        printf("Initialization succeeded\n");
    }

    vtkObjectBase *pConeSource = NULL;

    if (PyVtk_CreateVtkObject(pIntrospector, "vtkConeSource", pConeSource) == OK)
    {
        printf("Object creation succeeded\n");
    }

    return 0;
}

int PyVtk_InitIntrospector(
    PyObject *pIntrospector)
{
    /* Activating virtual environment */
#ifdef _DEBUG 
    // For Visual Studio debug builds
    const wchar_t *sPyHome = L"venv-dbg";
#else
    // For release builds
    const wchar_t *sPyHome = L"venv";
#endif
    Py_SetPythonHome(sPyHome);

    /* Initializing Python environment and setting PYTHONPATH. */
    Py_Initialize();

    PyRun_SimpleString("import sys\nimport os");
    PyRun_SimpleString("sys.path.append( os.path.dirname(os.getcwd()) )");
    PyRun_SimpleString("sys.path.append(\".\")");
    PyRun_SimpleString("import importlib.machinery as m");
    PyRun_SimpleString("print(m.all_suffixes())");

    /* Decode module from its name. Returns error if the name is not decodable. */
    PyObject *pIntrospectorModuleName = PyUnicode_DecodeFSDefault("Introspector");
    if (pIntrospectorModuleName == NULL)
    {
        fprintf(stderr, "Fatal error: cannot decode module name\n");
        return PYTHON_INTROSPECTION_STRING_DECODE_ERROR;
    }

    /* Imports the module previously decoded. Returns error if the module is not found. */
    PyObject *pIntrospectorModule = PyImport_Import(pIntrospectorModuleName);
    if (pIntrospectorModule == NULL)
    {
        if (PyErr_Occurred())
        {
            PyErr_Print();
        }
        fprintf(stderr, "Failed to load \"Introspector\"\n");
        Py_DECREF(pIntrospectorModuleName);
        return PYTHON_INTROSPECTION_MODULE_LOAD_ERROR;
    }

    /* Looks for the Introspector class in the module. If it does not find it, returns and error. */
    PyObject* pIntrospectorClass = PyObject_GetAttrString(pIntrospectorModule, "Introspector");
    if (pIntrospectorClass == NULL || !PyCallable_Check(pIntrospectorClass))
    {
        if (PyErr_Occurred())
        {
            PyErr_Print();
        }
        fprintf(stderr, "Cannot find class \"Introspector\"\n");
        if (pIntrospectorClass != NULL)
        {
            Py_DECREF(pIntrospectorClass);
        }
        Py_DECREF(pIntrospectorModuleName);
        Py_DECREF(pIntrospectorModule);
        return PYTHON_INTROSPECTION_CLASS_NOT_FOUND_ERROR;
    }

    /* Instantiates an Introspector object. If the call returns NULL there was an error
       creating the object, and thus it returns error. */
    pIntrospector = PyObject_CallObject(pIntrospectorClass, NULL);
    if (pIntrospector == NULL)
    {
        if (PyErr_Occurred())
        {
            PyErr_Print();
        }
        fprintf(stderr, "Introspector instantiation failed\n");
        Py_DECREF(pIntrospectorModuleName);
        Py_DECREF(pIntrospectorModule);
        Py_DECREF(pIntrospectorClass);
        return PYTHON_INTROSPECTION_OBJECT_CREATION_ERROR;
    }

    /* Decreasing reference to local data. */
    Py_DECREF(pIntrospectorModuleName);
    Py_DECREF(pIntrospectorModule);
    Py_DECREF(pIntrospectorClass);
    return OK;
}

我没有将代码添加到PyVtk_CreateVtkObject函数中,因为它不会输入它,但是如果我不添加调用之后PyVtk_InitIntroepsctor它不会给出上述错误。最后,如果我import Introspector自己在 Python 解释器中,它工作正常。

是否有解决方案可以在 Debug 或 Release 中运行它?我无法绕开它......

PS:我已经尝试过使用 Boost::Python,我有两个问题,因为它也给我带来了问题。

更新 1:特别是,当我这样做时会抛出异常:

PyObject *pIntrospectorModule = PyImport_Import(pIntrospectorModuleName);

更新 2:我已将问题进一步缩小到此:每当我vtk从嵌入式解释器中导入包时,它都会在此代码上引发访问冲突:

// Add special attribute __vtkname__
PyObject *s = PyString_FromString(classname);
PyDict_SetItemString(pytype->tp_dict, "__vtkname__", s);
Py_DECREF(s); // <-- In particular on this Py_DECREF

如果我尝试导入其他任何东西,似乎没有问题。

标签: pythonc++visual-studio-2017vtkpython-embedding

解决方案


推荐阅读