Home  >  Article  >  Backend Development  >  An in-depth analysis of C++ calling Python modules

An in-depth analysis of C++ calling Python modules

高洛峰
高洛峰Original
2017-02-20 10:37:131243browse

Python provides a C++ library that allows developers to easily call Python modules from C++ programs. Next, through this article, I will introduce you to the relevant knowledge of C++ calling Python modules. Friends who need it can refer to it

Generally, those who have developed games know that Lua and C++ can be well combined, learn from each other's strengths, and use Lua scripts Used like a dynamic link library, it makes good use of the flexibility of script development. As a popular general-purpose scripting language, Python can also do it. In a C++ application, we can use a set of plug-ins to implement some functions with a unified interface. Generally, plug-ins are implemented using dynamic link libraries. If plug-ins change frequently, we can use Python instead of dynamic link libraries. Plug-ins (which can be called dynamic link libraries in text form) make it easy to rewrite script code according to changes in requirements, instead of having to recompile and link binary dynamic link libraries. Flexibility is greatly improved.

As a glue language, Python can easily call C, C++ and other languages, and can also call Python modules through other languages.

Python provides a C++ library that allows developers to easily call Python modules from C++ programs.

For specific documentation, please refer to the official guide:

Embedding Python in Another Application

Calling method

1 Link to Python calling library

The Python installation directory already contains header files (include directory) and library files (python27.lib under Windows).

You need to link to this library before using it.

2 Directly call the Python statement

<code class="language-cpp hljs ">#include "python/Python.h"
int main()
{
Py_Initialize(); ## 初始化
PyRun_SimpleString("print &#39;hello&#39;");
Py_Finalize(); ## 释放资源
}
</code>

3 Load the Python module and call the function

~/test directory contains test .py :

<code class="language-python hljs ">def test_add(a, b):
print &#39;add &#39;, a, &#39; and &#39;, b
return a+b</code>

The test_add function can be called through the following code:

<code class="language-cpp hljs ">#include "python/Python.h"
#include <iostream>
using namespace std;
int main()
{
Py_Initialize(); // 初始化
// 将Python工作路径切换到待调用模块所在目录,一定要保证路径名的正确性
string path = "~/test";
string chdir_cmd = string("sys.path.append(\"") + path + "\")";
const char* cstr_cmd = chdir_cmd.c_str();
PyRun_SimpleString("import sys");
PyRun_SimpleString(cstr_cmd);
// 加载模块
PyObject* moduleName = PyString_FromString("test"); //模块名,不是文件名
PyObject* pModule = PyImport_Import(moduleName);
if (!pModule) // 加载模块失败
{
cout << "[ERROR] Python get module failed." << endl;
return 0;
}
cout << "[INFO] Python get module succeed." << endl;
// 加载函数
PyObject* pv = PyObject_GetAttrString(pModule, "test_add");
if (!pv || !PyCallable_Check(pv)) // 验证是否加载成功
{
cout << "[ERROR] Can&#39;t find funftion (test_add)" << endl;
return 0;
}
cout << "[INFO] Get function (test_add) succeed." << endl;
// 设置参数
PyObject* args = PyTuple_New(2); // 2个参数
PyObject* arg1 = PyInt_FromLong(4); // 参数一设为4
PyObject* arg2 = PyInt_FromLong(3); // 参数二设为3
PyTuple_SetItem(args, 0, arg1);
PyTuple_SetItem(args, 1, arg2);
// 调用函数
PyObject* pRet = PyObject_CallObject(pv, args);
// 获取参数
if (pRet) // 验证是否调用成功
{
long result = PyInt_AsLong(pRet);
cout << "result:" << result;
}
Py_Finalize(); ## 释放资源
return 0;
}
</iostream></code>

Parameter passing

1 C++ passes parameters to Python

The parameters of Python are actually tuples, so passing parameters is actually constructing a suitable tuple.

There are two commonly used methods:

Use PyTuple_New to create a tuple, and PyTuple_SetItem to set the tuple value

<code class="language-cpp hljs ">PyObject* args = PyTuple_New(3);
PyObject* arg1 = Py_BuildValue("i", 100); // 整数参数
PyObject* arg2 = Py_BuildValue("f", 3.14); // 浮点数参数
PyObject* arg3 = Py_BuildValue("s", "hello"); // 字符串参数
PyTuple_SetItem(args, 0, arg1);
PyTuple_SetItem(args, 1, arg2);
PyTuple_SetItem(args, 2, arg3);</code>

directly Use Py_BuildValue to construct a tuple

<code class="language-cpp hljs ">PyObject* args = Py_BuildValue("ifs", 100, 3.14, "hello");
PyObject* args = Py_BuildValue("()"); // 无参函数</code>

For format strings such as i, s, f, please refer to the format string

2 Convert Python Return Value

What you get when calling Python are PyObject objects, so you need to use some functions in the library provided by Python to convert the return value to C++, such as PyInt_AsLong, PyFloat_AsDouble, PyString_AsString, etc.

You can also use the PyArg_ParseTuple function to parse the return value as a tuple.

PyArg_Parse is also a conversion function that is very convenient to use.

PyArg_ParseTuple and PyArg_Parse both use format strings

Notes

You need to switch the Python working directory to the location of the module The path is loaded according to the module name instead of the file name. Module loading or function loading needs to be verified successfully, otherwise it may cause stack errors and cause the program to crash. Py_DECREF(PyObject*) needs to be used to dereference the object (for Python garbage collection)

The above is the relevant knowledge of C++ calling Python modules introduced by the editor. I hope it will be helpful to everyone!

For more in-depth analysis of C++ calling Python modules, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn