C++ 调用 Python 函数

C++调用Python函数方法详解

有些操作使用python来完成会更方便,比如执行一些网络请求、爬虫等操作。

环境声明

Visual Studio C++14

Python313

要把python文件和cpp文件放在同一目录下。

Python

新建一个名为pyif.py(可自定义)的文件,并写入以下测试函数,由C++代码输入名字参数,然后由python构造一个字典列表并返回。

def test_cpp_intf(name):
    dict_list =[]
    dict = {
        'name': name
    }
    dict_list .append(name_dict)
    return dict_list

C++

环境配置

1. 在Visual Studio项目属性页-Release-VC++目录-包含目录添加python的include路径

C:\Program Files\Python313\include

2. 在Visual Studio项目属性页-Release-VC++目录-库目录添加python的libs路径

C:\Program Files\Python313\libs

源代码

// 其它包含头文件
#include <Python.h>

void CallPyFunc() {
	PyObject* pModule = nullptr;
	PyObject* pFunc = nullptr;
	PyObject* pArgs = nullptr;
	PyObject* pName = nullptr;
	PyObject* pResult = nullptr;
	const wchar_t* inputName = L"帅哥";

	Py_Initialize();
	PyRun_SimpleString("import sys");
	PyRun_SimpleString("sys.path.append('.')");

	pModule = PyImport_ImportModule("pyif");// python file name
	if (pModule == nullptr) {
		std::cout << "Can not import module" << std::endl;
		goto Cleanup;
	}

	pFunc = PyObject_GetAttrString(pModule, "test_cpp_intf");// python function name
	if (pFunc == nullptr || PyCallable_Check(pFunc) == false) {
		std::cout << "Can not find the function or function is not callable" << std::endl;
		goto Cleanup;
	}

	// Prepare the input param
	pArgs = PyTuple_New(1);// new an empty tuple
	if (pArgs == nullptr) {
		std::cout << "PyTuple_New failed" << std::endl;
		goto Cleanup;
	}
	pName = PyUnicode_FromWideChar(inputName, -1);
	if (pName == nullptr) {
		std::cout << "PyUnicode_FromWideChar failed" << std::endl;
		goto Cleanup;
	}
	// Inser pName to the tuple. Tuple steals reference, so do not Py_DECREF(Decrease Reference)
	PyTuple_SetItem(pArgs, 0, pName);

	pResult = PyObject_CallObject(pFunc, pArgs);// 调用函数,返回一个字典列表
	if (pResult == nullptr || PyList_Check(pResult) == false) {// 检查是不是列表
		std::cout << "PyObject_CallObject failed or result is not a list" << std::endl;
		goto Cleanup;
	}

    for (Py_ssize_t i = 0; i < PyList_Size(pResult); i++) {
		PyObject* dict= PyList_GetItem(pResult, i);
		if (PyDict_Check(dict) == false) {// 检查是不是字典
			continue;
		}

        // 解析字典
		std::string name = ParsePyDictValueByKey(dict, "name");

        std::cout << name<< std::endl;
    }

Cleanup:
	if (pResult) Py_DECREF(pResult);
	if (pArgs) Py_DECREF(pArgs);
	if (pFunc) Py_DECREF(pFunc);
	if (pModule) Py_DECREF(pModule);
	Py_Finalize();
}


std::string ParsePyDictValueByKey(PyObject* dict, const char* key) {
	PyObject* pValue = PyDict_GetItemString(dict, key);
	if (pValue) {
		if (PyUnicode_Check(pValue)) {
			PyObject* temp_bytes = PyUnicode_AsEncodedString(pValue, "ANSI", "strict");
			if (temp_bytes != NULL) {
				std::string result = PyBytes_AS_STRING(temp_bytes);
				Py_DECREF(temp_bytes);
				return result;
			}
		}
		else if (PyLong_Check(pValue)) {
			long value = PyLong_AsLong(pValue);
			return std::to_string(value);
		}
		else if (PyFloat_Check(pValue)) {
			double value = PyFloat_AsDouble(pValue);
			return std::to_string(static_cast<int>(value));
		}
	}
	return "";
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值