C++builder中的人工智能(26):如何在C++应用中使用Python语言?

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()循环和一些数学过程(floorsqrt等),显示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示例。

  1. 创建一个新的 C++ Builder应用程序(VCL或FMX)
  2. 添加一个 Memo (TMemo) 以输入一些Python代码,这将是 Memo1
  3. 再添加一个 Memo (TMemo) 用于Python代码的输出,这将是 Memo2
  4. 添加一个 Button (TButton) 以运行Python代码,这将是 Button1,将其标题或文本设置为“保存并运行”
  5. 双击 Button1,这将生成 Button1Click()
  6. 在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++应用程序中。这个过程包括三个步骤:

  1. 保存Python代码:将用户在C++应用程序的Memo1文本框中编写的Python代码保存到一个临时文件tmp.py中。
  2. 执行Python脚本:使用C++的system()函数调用Python解释器执行tmp.py文件,并将标准输出重定向到tmp.out文件中。
  3. 读取输出:从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;
}

这个程序的工作流程如下:

  1. 使用#include <iostream>来包含标准输入输出流库,以便在程序中使用std::coutstd::cin

  2. main函数是程序的入口点。

  3. 使用std::system函数调用Python解释器执行tmp.py脚本,并将输出重定向到tmp.out文件。std::system函数可以执行操作系统的命令行命令。

  4. 程序可以使用tmp.out文件进行进一步的处理。在这个示例中,我们使用std::ifstream(输入文件流)来打开tmp.out文件,并使用std::getline函数逐行读取文件内容,然后将每行输出到控制台。

  5. 最后,程序返回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 代码。以下是一些常用的函数和概念:

  1. Py_Initialize()

    • 初始化 Python 解释器。在调用任何其他 Python API 之前,必须先调用此函数。
  2. Py_Finalize()

    • 关闭 Python 解释器。在退出程序前调用,以清理分配的内存和资源。
  3. PyRun_SimpleString()

    • 执行一个简单的 Python 字符串。如果发生错误,它会打印 traceback 并返回 -1
  4. PyRun_SimpleFile()

    • 从文件执行 Python 代码。与 PyRun_SimpleString() 类似,但是从文件中读取 Python 代码。
  5. PyObject_CallObject()

    • 调用一个 Python 对象,通常是一个函数。你需要传递函数对象和参数元组。
  6. PyObject_CallMethod()

    • 调用一个 Python 对象的方法。你需要传递对象、方法名和参数字符串。
  7. PyImport_ImportModule()

    • 导入一个 Python 模块。返回的是模块对象。
  8. PyDict_GetItemString()

    • 从字典对象中使用字符串键检索值。
  9. Py_BuildValue()PyArg_ParseTuple()

    • Py_BuildValue() 用于创建新的 Python 对象从 C 数据类型。
    • PyArg_ParseTuple() 用于从 Python 对象解析参数到 C 数据类型。
  10. PyEval_EvalCode()

    • 执行编译的代码对象。
  11. PyErr_Print()

    • 打印当前 Python 错误到 stderr。
  12. PyErr_Occurred()

    • 检查是否有 Python 异常发生。
  13. PyErr_Clear()

    • 清除当前错误。
  14. 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 环境变量配置正确的情况下编译和运行。在实际应用中,你可能需要根据实际情况调整模块名和函数名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caridle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值