侧边栏壁纸
博主头像
G

  • 累计撰写 85 篇文章
  • 累计创建 48 个标签
  • 累计收到 5 条评论

目 录CONTENT

文章目录

C++多线程运行python c api方法

G
G
2024-05-07 / 0 评论 / 0 点赞 / 66 阅读 / 550 字 / 正在检测是否收录...

封装一个python资源锁类,在调用python api时调用

class PyThreadStateLock {
public:
    PyThreadStateLock() {
        state = PyGILState_Ensure();
    }
    ~PyThreadStateLock() {
        PyGILState_Release(state);
    }
public:
    PyGILState_STATE state;
};

主线程中完成初始化

    // 搜索目录设定
    Py_SetPythonHome(PathHelper::StdApplicationFile(L"plugin").c_str());
    // 初始化
    Py_Initialize();
    if (!Py_IsInitialized())
    {
        LOG_EX("python初始化失败");
        return -1;
    }
    // 初始化线程支持
    PyEval_InitThreads();
    // 启动子线程前执行 为了释放PyEval_InitThreads获取的全局锁,否则子线程可能无法获取到全局锁
    PyEval_ReleaseThread(PyThreadState_Get());
    
    // 启动线程执行python代码
   .......
   
    // 保证子线程调用都结束释放资源
    PyGILState_Ensure();
    Py_Finalize();

python封装代码

template<typename... Args>
inline int call_python_func(std::string module_name, std::string func_name,std::string & func_result,std::string args_type, Args... args) {
    PyThreadStateLock PyThreadLock;
    PyObject* ptype, * pvalue, * ptraceback;
	
    LOG_EX("Py_GetPythonHome %ws", Py_GetPythonHome());
    LOG_EX("Py_GetProgramFullPath %ws", Py_GetProgramFullPath());
    LOG_EX("Py_GetPath %ws", Py_GetPath());
    LOG_EX("Py_GetPrefix %ws", Py_GetPrefix());
    LOG_EX("Py_GetExecPrefix %ws", Py_GetExecPrefix());
    LOG_EX("Py_GetExecPrefix %ws", Py_GetExecPrefix());

    PyObject* pModule = NULL;//声明变量
    PyObject* pFunc = NULL;// 声明变量
    pModule = PyImport_ImportModule(module_name.c_str());//这里是要调用的文件名
    if (pModule == NULL)
    {
        LOG_EX("py模块加载失败:%s",module_name.c_str());
        //PyErr_Fetch(&ptype, &pvalue, &ptraceback);
        //	// 检查异常类型
        //PyObject* ptype_str = PyObject_Str(ptype);
        //const char* type_str = PyUnicode_AsUTF8(ptype_str);
        //LOG_EX("Exception type: %s\n", type_str);
        //Py_XDECREF(ptype_str); // 释放对象引用

        //// 获取异常值
        //PyObject* pvalue_str = PyObject_Str(pvalue);
        //const char* value_str = PyUnicode_AsUTF8(pvalue_str);
        //LOG_EX("Exception value: %s\n", value_str);
        //Py_XDECREF(pvalue_str); // 释放对象引用

        //// 清除异常信息
        //PyErr_Clear();
        goto pyfunc_end;
    }
    else {
        pFunc = PyObject_GetAttrString(pModule, func_name.c_str());
        //给python函数参数赋值
        PyObject* pArgs = NULL;
        if (args_type != "") {
            pArgs = Py_BuildValue(args_type.c_str(), args...);
        }

        //调用函数
        PyObject* pRet = PyObject_CallObject(pFunc, pArgs);
        char *res = nullptr;
        //转换返回类型
        PyArg_Parse(pRet, "s", &res);
        if (res) {
            func_result = res;
        }
        else {
            LOG_EX("python方法调用失败");
        }
        Py_DecRef(pRet);
        Py_DecRef(pArgs);
        Py_DecRef(pFunc);
    }
pyfunc_end:
    return 0;
}

调用示例

// 调用python_module中的Main函数 参数类型为sss(三个字符串类型),返回值为std::string 存储到js_doc中
call_python_func(“python_module”, "Main", js_doc, "sss", “1”, “2”, “3”);
0

评论区