首頁 > 軟體

C++如何呼叫簡單的python程式

2023-02-20 06:01:15

一、基本環境的搭建

首先,用vs建立一個win32的控制檯應用程式專案(vs2017及以上怎麼建立百度一下就知道了)。

然後設定好python的環境變數(把include資料夾加到包含目錄,libs資料夾加到庫目錄,最好還把include資料夾加到附加包含目錄)。

如下圖所示:

最後,把python36.libs檔案加到依賴項(如果是debug編譯,要重新命名python36.libs為python36_d.libs,然後加到依賴項)

如下圖所示。

二、直接在C++裡面呼叫執行python語句

搭建好一中的環境之後,在原始檔裡面新建一個cpp檔案,cpp裡面的程式碼如下。

程式碼很簡單,應該一看就懂了吧。

#include <Python.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
	//***python呼叫***//
	//直接在C++裡面執行python語句
	void usePythonWorld();
	usePythonWorld();
	system("pause");
}
void usePythonWorld()//呼叫無引數函數
{
	//初始化python模組:用來分配python直譯器所使用的全域性資源
	Py_SetPath(L"D:/chengxuanzhuang/anaconda/envs/python3.6/Lib");
	Py_Initialize();
	if (!Py_IsInitialized())// 檢查初始化是否成功
	{
		cout << "初始化失敗" << endl;
		Py_Finalize();
	}
	//直接呼叫python語句(沒有成功)
	PyRun_SimpleString("print('in python'n)");
	Py_Finalize();

}

需要注意的地方是,在使用PyRun_SimpleString之前,一定要使用 Py_Initialize()初始化Python。

三、呼叫python指令碼檔案裡面的定義函數

呼叫不含引數的函數

搭建好一中的環境之後,在原始檔裡面新建一個cpp檔案,cpp裡面的程式碼如下。

程式碼很簡單,應該一看就懂了吧。

#include <Python.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
	//***python呼叫***//
	//呼叫無引數python函數
	bool InvokeNonParasFuncByAPI(string module, string func);
	InvokeNonParasFuncByAPI("PythonGreet", "Hello");
	system("pause");
}
bool InvokeNonParasFuncByAPI(string module, string func)
{
	Py_SetPath(L"D:/chengxuanzhuang/anaconda/envs/python3.6/Lib");
	Py_Initialize();
	if (!Py_IsInitialized())
	{
		return false;
	}
	try
	{
		//將當前目錄切換到python指令碼放置的目錄,因為初始化到了python的全域性資源下,所以只能只用python語句
		PyRun_SimpleString("import sysn");
		PyRun_SimpleString("sys.path.append('./')");//這個一個簡單的執行python指令碼命令的函數,由於路徑是'./',所以python指令碼要放在這個專案的根目錄

		//呼叫pyhton指令碼
		PyObject* moduleName = PyUnicode_FromString(module.c_str()); 
		PyObject* pModule = PyImport_Import(moduleName);
		if (!pModule)
		{
			cout << "Import Module Failed" << endl;
			return false;
		}
		PyObject* pFunc = PyObject_GetAttrString(pModule, func.c_str());//呼叫指令碼裡面的函數
		if (!pFunc || !PyCallable_Check(pFunc)) //這裡面的這個函數是用來判斷方法是否有效 
		{
			cout << "Get Function Failed!" << endl;
			return false;
		}
		PyObject* pResult = PyObject_CallObject(pFunc, nullptr);//使用python指令碼裡面的函數
		if (!pResult)
		{
			cout << "Get Result of Function Failed!" << endl;
			return false;
		}
	}
	catch (...)
	{
		PyErr_Print(); //如果出錯會列印出錯誤
		PyErr_Clear();
		Py_Finalize();
		return false;
	}
	Py_Finalize();
	return true;
}

呼叫含一個引數的函數

搭建好一中的環境之後,在原始檔裡面新建一個cpp檔案,cpp裡面的程式碼如下。

程式碼很簡單,應該一看就懂了吧。

其中的demo_test是python指令碼檔名,注意不是demo_test.py。最後把這個python指令碼檔案和cpp檔案放在同一個資料夾下(注意不是放在原始檔裡,而是找到cpp檔案所在的資料夾,放到這個資料夾裡。

如下。如果是在專案裡直接建立的python檔案,會自動存放到這個資料夾下)

不出意外,就可以執行這個cpp檔案了。

呼叫含多個引數的函數

搭建好一中的環境之後,在原始檔裡面新建一個cpp檔案,cpp裡面的程式碼如下。

程式碼很簡單,應該一看就懂了吧。

#include <Python.h>
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
	//***python呼叫***//
	//呼叫含引數的python函數
	vector<int> paras;
	paras.push_back(3);
	paras.push_back(4);
	bool InvokeFuncbyAPI(string module, string func, vector<int> paras);
	InvokeFuncbyAPI("PythonCalc", "Add",paras);
	system("pause");
}
bool InvokeFuncbyAPI(string module, string func,vector<int> paras)
{
	Py_SetPath(L"D:/chengxuanzhuang/anaconda/envs/python3.6/Lib");
	Py_Initialize();
	if (!Py_IsInitialized())
	{
		return false;
	}
	try
	{
		//將當前目錄切換到python指令碼放置的目錄,因為初始化到了python的全域性資源下,所以只能只用python語句
		PyRun_SimpleString("import sysn");
		PyRun_SimpleString("sys.path.append('./')");//這個一個簡單的執行python指令碼命令的函數,由於路徑是'./',所以python指令碼要放在這個專案的根目錄

		//呼叫pyhton指令碼
		PyObject* moduleName = PyUnicode_FromString(module.c_str());
		PyObject* pModule = PyImport_Import(moduleName);
		if (!pModule)
		{
			cout << "Import Module Failed" << endl;
			return false;
		}
		PyObject* pFunc = PyObject_GetAttrString(pModule, func.c_str());//呼叫指令碼裡面的函數
		if (!pFunc || !PyCallable_Check(pFunc)) //這裡面的這個函數是用來判斷方法是否有效 
		{
			cout << "Get Function Failed!" << endl;
			return false;
		}
		PyObject* pResult = nullptr; //建立一個獲取結果的python資料結構
		PyObject* args = PyTuple_New((int)paras.size());//建立一個存放入參的python資料結構
		for (int i = 0; i < (int)paras.size(); i++)
		{
			PyTuple_SetItem(args, i, PyLong_FromLong(paras[i])); //將C++的引數轉化為python的引數
		}
		pResult = PyObject_CallObject(pFunc, args);
		if (!pResult)
		{
			cout << "Get Result of Function Failed!" << endl;
			return false;
		}
		cout << "Result = " << PyLong_AsLong(pResult) << "by python api" << endl;

	}
	catch (...)
	{
		PyErr_Print();//如果出錯會列印出錯誤
		PyErr_Clear();
		Py_Finalize();
		return false;
	}
	Py_Finalize();
	return true;
}

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com