Python是一个非常流行且拥有许多实用库的编程语言。特别是在人工智能(AI)和机器学习(ML)领域,Python表现出色。如果您是C++开发者,您可能希望您的用户能够使用您的应用程序中的Python编写的AI模块或框架来分析数据。想象一下,用户只需点击几个按钮就能进行一些繁重的AI分析。这样,您就能充分利用C++的原始速度和力量,同时运行Python模块。您知道吗,您可以在C++ IDE中非常容易地做到这一点。在本文中,我们将展示如何将您的C++应用程序与Python语言集成。
目录
- 为什么我要在C++应用中使用Python语言?
- 为什么我要在应用中使用C++而不是Python?
- 我可以在C++应用中的哪些地方使用Python语言?
- 如何在C++应用中使用Python语言?
- 在C++应用中使用Python语言的更多信息
- 如何在C++ VCL应用中使用Python语言?
- 如何在跨平台C++ FMX应用中使用Python语言?
- 如何在C++控制台应用中使用Python语言?
为什么我要在C++应用中使用Python语言?
在当今的编程世界中,Python编程语言非常受欢迎,可能仅次于C++。Python易于使用,并且因为得到谷歌等大公司的支持而更受欢迎。Python特别成功的领域之一是AI技术和机器学习的库和框架。它是一种伟大的面向对象的、解释型的、交互式的编程语言。Python具有非常清晰的语法。它具有模块、类、异常、非常高级的动态数据类型和动态类型。它有许多系统调用和库的接口,以及各种窗口系统的接口。新的内置Python模块可以轻松地用C或C++编写。Python也可以作为其他语言编写的应用程序的脚本扩展,这些应用程序从其易用性中受益。Python是免费使用的。更多信息可以在他们的官方网站找到:Welcome to Python.org
我们应该注意,Python可以在Delphi项目中使用,这个质数函数之前在Delphi和Python中测试过:https://www.youtube.com/watch?v=aCz5h96ObUM 与Kiriakos Vlahos一起。在这里,我们受到这个视频的启发,尝试在C++中对相同的函数进行相同的测试。在这篇文章中详细解释了如何在现代C++中找到质数。
为什么我要在应用中使用C++而不是Python?
C和C++是最快速且最强大的编程语言之一,它们可以轻松地进行尽可能快的计算。例如,C++ Builder是一个伟大的IDE,包括了Win32、Win64、Android和iOS的编译器。C++Builder既有CLANG增强型C/C++编译器,也有Embarcadero的新Bcc C/C++编译器。它还具有现代的、高生产力的RAD Studio IDE、调试工具和企业级连接性,以加速跨平台UI开发。您可以轻松地开发基于GUI的应用程序,因为它附带了屡获殊荣的VCL框架,用于高性能的原生Windows应用程序和功能强大的FireMonkey (FMX)框架,用于跨平台UI。还有一个免费的C++ Builder社区版,学生、初学者和初创企业也可以使用,但有限制。
在我们对相同PC系统上的不同质数测试中(我发现这个测试是一个很好的测试,它包含整数、浮点数、浮点函数、逻辑函数和迭代),我们的测试表明,C++在计算64位质数时比Python快约9.4倍,而在32位上快约17.8倍。计算质数是一个很好的测试,它使用了一些基本的逻辑操作和数学函数。这个过程包括逻辑if()
语句、for()
循环和一些数学过程(floor
、sqrt
等),显示C++在数学操作上非常快速。这些测试可以在不同的操作中进行,以比较语言。即使是写得最好的Python也无法接近类似C++应用的速度。
在其他一些例子中,Python可能比C++慢20、50、100、200倍。别忘了,Python在“幕后”使用C++模块。当您运行一些命令时,它使用这些模块,使其在模块函数中更快,即在AI应用中。
我可以在C++应用中的哪些地方使用Python语言?
如果您想在应用程序中使用Python特性,有一个简单的方法可以做到这一点。首先,让我们举一个例子:
例如,您开发了一个非常复杂的C++应用程序,该应用程序可以从不同的连接模块获取即时图像,假设用户可以通过您的应用程序对这些图像进行编辑,并执行许多操作,还有用户登录和安全模块、数据库连接等。在某个时候,您希望用户知道那幅画中有什么,或者您希望您的应用程序在视野中有人类(或汽车、野生动物)时发出警告。为此,您有3个不同的选择:
- 您可以在C++中开发自己的深度学习库
- 您可以在C++中使用第三方深度学习库(开源或付费)
- 您可以使用Python及其框架,并从互联网上适应一些示例
假设您找到了一些可以学习和分析这些图像的简单Python代码,并希望在您美观的现代高分辨率C++应用程序中使用这些Python代码。在这种情况下,最好的做法是遵循第三个选择。在下面的帖子中,我们解释了第三个选择,它简单且易于使用最新的Python,并轻松运行您找到的最新Python代码。
如何在C++应用中使用Python语言?
首先,您需要一个适当版本的Python和您想要使用的Python代码。Python是免费使用的,更多信息可以在他们的官方网站找到:https://www.python.org/,从那里安装它。然后,您可能需要在Python中安装更多的模块或框架。确保Python编译器在命令控制台的任何路径中运行。现在让我们给出一个非常简单且现代的C++ Builder VCL示例。
- 创建一个新的 C++ Builder应用程序(VCL或FMX)
- 添加一个 Memo (TMemo) 以输入一些Python代码,这将是 Memo1
- 再添加一个 Memo (TMemo) 用于Python代码的输出,这将是 Memo2
- 添加一个 Button (TButton) 以运行Python代码,这将是 Button1,将其标题或文本设置为“保存并运行”
- 双击 Button1,这将生成 Button1Click()
- 在Button1Click()事件中添加以下代码:
// 保存Memo1中写的Python代码
Memo1->Lines->SaveToFile("tmp.py");
// 运行tmp.py Python文件,并输出到tmp.out
std::system("python tmp.py > tmp.out");
// 从tmp.out加载输出文件
Memo2->Lines->LoadFromFile("tmp.out");
当用户点击按钮时,首先,我们将Memo1中编写的Python代码保存到一个名为tmp.py
的文件中:
Memo1->Lines->SaveToFile("tmp.py");
然后,我们将使用system()
命令运行这个tmp.py
Python文件,并将输出重定向到tmp.out
文件中:
std::system("python tmp.py > tmp.out");
最后,我们将从tmp.out
文件中读取输出内容:
// 加载输出文件
Memo2->Lines->LoadFromFile("tmp.out");
这段代码是一个简单的示例,展示了如何在C++应用程序中执行Python脚本并将结果返回到C++应用程序中。这个过程包括三个步骤:
- 保存Python代码:将用户在C++应用程序的
Memo1
文本框中编写的Python代码保存到一个临时文件tmp.py
中。 - 执行Python脚本:使用C++的
system()
函数调用Python解释器执行tmp.py
文件,并将标准输出重定向到tmp.out
文件中。 - 读取输出:从
tmp.out
文件中读取Python脚本的输出,并将结果显示在C++应用程序的Memo2
文本框中。
这种方法允许C++应用程序利用Python的强大功能,例如数据分析、机器学习等,同时保持C++应用程序的性能优势。
在C++应用中使用Python语言的更多信息
简而言之,这3个步骤一起在C++ Builder应用程序中非常简单。
// 保存写的Python代码
Memo1->Lines->SaveToFile("tmp.py");
// 在这个文件上运行Python,并将输出到另一个文件
std::system("python tmp.py > tmp.out");
// 从输出文件加载
Memo2->Lines->LoadFromFile("tmp.out");
这里有一个运行Python代码的VCL示例:
如何在C++ VCL应用中使用Python语言?
这里有一个完整的C++ Builder VCL示例:
#include <vcl.h>
#pragma hdrstop
#include "Python_Runner_Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Save written Python codes
Memo1->Lines->SaveToFile("tmp.py");
// Run Python on this file and output to another file
std::system("python tmp.py > tmp.out");
// Load output file
Memo2->Lines->LoadFromFile("tmp.out");
}
如何在跨平台C++ FMX应用中使用Python语言?
这里有一个C++ Builder中的FMX示例:
#include <fmx.h>
#pragma hdrstop
#include "Python_Runner_Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Save written Python codes
Memo1->Lines->SaveToFile("tmp.py");
// Run Python on this file and output to another file
std::system("python tmp.py > tmp.out");
// Load output file
Memo2->Lines->LoadFromFile("tmp.out");
}
在C++控制台应用程序中使用Python语言的方法相对简单。以下是一个可以在任何Windows编译器中使用的简单控制台应用程序示例,例如C++ Builder、Dev-C++、MSVC、VSCode、GNU gcc g++等。
#include <iostream>
int main() {
// 运行Python脚本,并将输出重定向到另一个文件
std::system("python tmp.py > tmp.out");
// 使用tmp.out文件(分析、编辑、显示等)
// 这里可以添加代码来读取tmp.out文件,并在C++程序中处理输出结果
// 例如,读取tmp.out文件并打印到控制台
std::ifstream outFile("tmp.out");
std::string line;
while (std::getline(outFile, line)) {
std::cout << line << std::endl;
}
outFile.close();
return 0;
}
这个程序的工作流程如下:
-
使用
#include <iostream>
来包含标准输入输出流库,以便在程序中使用std::cout
和std::cin
。 -
main
函数是程序的入口点。 -
使用
std::system
函数调用Python解释器执行tmp.py
脚本,并将输出重定向到tmp.out
文件。std::system
函数可以执行操作系统的命令行命令。 -
程序可以使用
tmp.out
文件进行进一步的处理。在这个示例中,我们使用std::ifstream
(输入文件流)来打开tmp.out
文件,并使用std::getline
函数逐行读取文件内容,然后将每行输出到控制台。 -
最后,程序返回0,表示成功执行。
这个示例展示了如何在C++控制台应用程序中调用Python脚本,并将Python脚本的输出作为C++程序的输入进行处理。这种方法可以让您在C++程序中利用Python的强大功能,例如数据处理、机器学习等,同时保持C++的性能优势。
事实上,上述的不算真正地 嵌入python脚本,python脚本提供直接的使用。
配置python的头文件
配置库文件
代码:
#include <iostream>
#include <tchar.h>
#include <Python.h>
#include <string>
#include <pylifecycle.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
// 1、初始化python接口 https://www.cnblogs.com/lidabo/p/17073441.html
Py_Initialize(); //使用python之前,要调用Py_Initialize();这个函数进行初始化
if (!Py_IsInitialized()) {
printf("初始化失败!");
return 0;
}
PyRun_SimpleString("print('hello')");
PyObject* pModule = NULL; //声明变量
// PyObject* pFunc1 = NULL;
// PyObject* pFunc2 = NULL;
// PyObject* pFunc3 = NULL;
// 2、初始化python系统文件路径,保证可以访问到 .py文件
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./script')");
// 3、调用python文件名,不用写后缀
pModule = PyImport_ImportModule("hello");
if (pModule == NULL)
{
cout << "hello.py:没找到" << endl;
}
pFunc3 = PyObject_GetAttrString(pModule, "func1"); //这里是要调用的函数名
PyObject* args2 = Py_BuildValue("ii", 25, 6);//给python函数参数赋值
PyObject* pRet = PyObject_CallObject(pFunc3, args2);//调用函数
int res = 0;
PyArg_Parse(pRet, "i", &res);//转换返回类型
cout << "res:" << res << endl; //输出结果
Py_Finalize(); // 与初始化对应
system("pause");
return 0;
}
#include <Python.h>
是 Python 嵌入式编程接口的头文件,它允许 C 或 C++ 程序直接嵌入和执行 Python 代码。以下是一些常用的函数和概念:
-
Py_Initialize():
- 初始化 Python 解释器。在调用任何其他 Python API 之前,必须先调用此函数。
-
Py_Finalize():
- 关闭 Python 解释器。在退出程序前调用,以清理分配的内存和资源。
-
PyRun_SimpleString():
- 执行一个简单的 Python 字符串。如果发生错误,它会打印 traceback 并返回
-1
。
- 执行一个简单的 Python 字符串。如果发生错误,它会打印 traceback 并返回
-
PyRun_SimpleFile():
- 从文件执行 Python 代码。与
PyRun_SimpleString()
类似,但是从文件中读取 Python 代码。
- 从文件执行 Python 代码。与
-
PyObject_CallObject():
- 调用一个 Python 对象,通常是一个函数。你需要传递函数对象和参数元组。
-
PyObject_CallMethod():
- 调用一个 Python 对象的方法。你需要传递对象、方法名和参数字符串。
-
PyImport_ImportModule():
- 导入一个 Python 模块。返回的是模块对象。
-
PyDict_GetItemString():
- 从字典对象中使用字符串键检索值。
-
Py_BuildValue() 和 PyArg_ParseTuple():
Py_BuildValue()
用于创建新的 Python 对象从 C 数据类型。PyArg_ParseTuple()
用于从 Python 对象解析参数到 C 数据类型。
-
PyEval_EvalCode():
- 执行编译的代码对象。
-
PyErr_Print():
- 打印当前 Python 错误到 stderr。
-
PyErr_Occurred():
- 检查是否有 Python 异常发生。
-
PyErr_Clear():
- 清除当前错误。
-
Py_INCREF() 和 Py_DECREF():
Py_INCREF()
增加对象的引用计数。Py_DECREF()
减少对象的引用计数。当引用计数为零时,对象会被销毁。
这些函数和概念是 Python 嵌入式编程的基础,允许 C/C++ 程序与 Python 解释器交互,执行 Python 代码,以及在两种语言之间传递数据。使用这些函数时,需要注意 Python 的引用计数和异常处理机制,以避免内存泄漏和程序崩溃。
下面是一个基本的示例,展示了如何在 C/C++ 程序中使用 Python.h
中的函数来嵌入和执行 Python 代码。这个示例包括初始化 Python 解释器、执行 Python 代码、调用 Python 函数、处理异常和清理。
#include <Python.h>
int main() {
// 初始化 Python 解释器
Py_Initialize();
// 检查 Python 解释器是否初始化成功
if (!Py_IsInitialized()) {
fprintf(stderr, "Python interpreter not initialized.\n");
return 1;
}
// 导入 Python 模块
PyObject *pName, *pModule;
pName = PyUnicode_DecodeFSDefault("mymodule"); // 假设模块名为 mymodule
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule != NULL) {
// 从模块中获取函数
PyObject *pFunc = PyObject_GetAttrString(pModule, "myfunction"); // 假设模块中有一个名为 myfunction 的函数
if (pFunc && PyCallable_Check(pFunc)) {
// 调用函数
PyObject *pArgs = PyTuple_New(0); // 无参数
PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
PyTuple_SetItem(pArgs, 0, pValue); // 将返回值设置为第一个参数
Py_DECREF(pArgs);
if (pValue != NULL) {
// 打印结果
printf("Result of call: %ld\n", PyLong_AsLong(pValue));
Py_DECREF(pValue);
} else {
// 处理调用错误
PyErr_Print();
fprintf(stderr, "Call failed\n");
}
Py_DECREF(pFunc);
} else {
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \"myfunction\"\n");
}
Py_DECREF(pModule);
} else {
PyErr_Print();
fprintf(stderr, "Failed to load \"mymodule\"\n");
}
// 清理 Python 解释器
Py_Finalize();
return 0;
}
在这个示例中,我们首先调用 Py_Initialize()
来初始化 Python 解释器。然后,我们尝试导入一个名为 mymodule
的 Python 模块,并从中获取一个名为 myfunction
的函数。如果函数存在且可调用,我们使用 PyObject_CallObject
来调用它,并将结果打印出来。如果在这个过程中发生任何错误,我们将使用 PyErr_Print()
来打印错误信息。最后,我们调用 Py_Finalize()
来清理 Python 解释器。
请注意,这个示例假设你已经有一个名为 mymodule.py
的 Python 模块,其中包含一个返回整数值的函数 myfunction
。此外,这个示例需要在 Python 环境变量配置正确的情况下编译和运行。在实际应用中,你可能需要根据实际情况调整模块名和函数名。