【FastCAE源码阅读6】C++与Python的集成,实现相互调用

分析FastCAE代码之前先看看C++与Python如何相互调用的。

一、C++调用Python

先写个C++调用Python的例子,然后再来看FastCAE集成Python就比较简单了。直接上代码:

#include <iostream>
#include "python.h"int main()
{Py_Initialize();PyRun_SimpleStringFlags("print('hello world') ", NULL);Py_Finalize();
}

代码功能很简单,就是执行打印hello world结束。其中,Py_Initialize()初始化Python环境。PyRun_SimpleStringFlags这个函数可以执行Python代码,Py_Finalize()关闭Python解析器。这个例子要跑起来麻烦的地方在项目配置:

  1. 配置头文件:Python安装目录下的include目录加入头文件目录。Visual Studio中操作路径是:属性–》 C/C++ --》 常规 --》 附加包含目录
    在这里插入图片描述
  2. 配置lib库目录:要将Python37.lib加入编译链接。Visual Studio中操作路径是:属性–》 链接器 --》 常规 --》 附加包含目录
    在这里插入图片描述同时,在“输入”–》“附加依赖项”中输入Python37.lib在这里插入图片描述
  3. 配置运行目录:配置dll文件所在目录,我这里直接更改的工作目录,这种方式不推荐。比较好的方式是配置"调试"–》"环境"中增加PATH变量。但这种方式我没有配成功,用的是更改工作目录,将工作目录直接指到python所在目录,如下图:在这里插入图片描述

运行起来就能看到打印的hello world了!

二、Python调用c++ dll库

Python可通过ctypes调用动态库。ctypes的使用资料很多。我这里就不再讲了。

三、FastCAE Python模块分析

FastCAE中与Python相关的代码同样分成两块:C++调用Python、Python调用C++。
C++调用Python相关的代码在PythonModule模块,Python调用C++是在预先导入的python脚本中,这些脚本会调用底层dll库,最总形成如下图所示的调用关系:
在这里插入图片描述

  1. PythonModule模块
    PythonModule模块总共只有5个类。其中PyAgent、PyInterpreter是核心,封装这C++调用Python的逻辑。
    在这里插入图片描述

先看一下PyAgent类头文件:

class PYTHONMODULEAPI PythonAgent : public QObject{Q_OBJECTpublic:static PythonAgent *getInstance(); // 获取单例接口void initialize(GUI::MainWindow *m); // 初始化void finalize();void submit(QString code, bool save = true); // 提交执行Python代码//后台执行,不在界面显示,也不保存void backstageExec(QString code);void submit(QStringList codes, bool save = true);void saveScript(QString fileName);bool execScript(QString fileName);void appCodeList(QString code);void lock();void unLock();bool isLocked();void appendOn();void appendOff();void execMessWinCode(QString code);QStringList getcodelist();void setNoGUI(bool nogui);signals:void printInfo(Common::Message type, QString m);void closeMainWindow();private:PythonAgent();~PythonAgent() = default;void connectSignals();private slots:void readerFinished();private:static PythonAgent *_instance;PyInterpreter *_interpreter{};RecordThread *_recordScript{};GUI::MainWindow *_mainWindow{};ScriptReader *_reader{};bool _islock{false};bool _append{true};bool _noGUI{false};};

这个类是个单例类,用的时候用getInstance获取实例。initialize()、submit()是主要的方法。initialize是主要是调用Py_Initialize初始化Python解析器,代码如下:

void PythonAgent::initialize(GUI::MainWindow* m)
{_mainWindow = m;connectSignals();Py_SetProgramName(L"FastCAE");Py_Initialize();if(!_interpreter->init(this))emit printInfo(Common::Message::Error, tr("Python Initialize failed!"));elseemit printInfo(Common::Message::Normal, tr("Python Initialized"));_recordScript = new RecordThread;_recordScript->start();
}

PyInterpreter类主要是import预先写好的Python脚本,这些脚本在该模块的py文件夹下。同时提供执行Python代码的入口,最终使用PyRun_SimpleStringFlags执行Python代码。

无法显示图片时显示的文字
预制的Python脚本
  1. Python脚本
    Python脚本中使用ctypes调用dll库。dll为了支持Python调用需声明调用的接口,并且为了防止C++编译器更改函数名,需用extern "C"进行修饰。以几何模块为例,其python接口声明在GeoCommandPy.h文件中,代码如下:
//声明为C接口,供Python脚本调用
extern "C"
{void GEOMETRYCOMMANDAPI CreateBox(char* name, double x, double y, double z, double l, double w, double h);void GEOMETRYCOMMANDAPI EditBox(int id, double x, double y, double z, double l, double w, double h);void GEOMETRYCOMMANDAPI CreateCylinder(char* name, double x, double y, double z, double l, double w, double h, double radius, double length);void GEOMETRYCOMMANDAPI EditCylinder(int id, double x, double y, double z, double l, double w, double h, double radius, double length);void GEOMETRYCOMMANDAPI CreateCone(char* name, double x, double y, double z, double l, double w, double h, double radius, double radius2, double length);void GEOMETRYCOMMANDAPI EditCone(int id, double x, double y, double z, double l, double w, double h, double radius, double radius2, double length);void GEOMETRYCOMMANDAPI CreateSphere(char* name, double x, double y, double z, double r);void GEOMETRYCOMMANDAPI EditSphere(int id, double x, double y, double z, double r);void GEOMETRYCOMMANDAPI CreatePoint(char* name, double x, double y, double z, double p1, double p2, double p3);void GEOMETRYCOMMANDAPI EditPoint(int id, double x, double y, double z, double p1, double p2, double p3);void GEOMETRYCOMMANDAPI CreateLine(char* name, double startpoint0, double startpoint1, double startpoint2,int method, double coor0, double coor1, double coor2, double len, double dir0, double dir1, double dir2, int reverse);void GEOMETRYCOMMANDAPI EditLine(int id, double startpoint0, double startpoint1, double startpoint2, int method, double coor0, double coor1, double coor2, double len, double dir0, double dir1, double dir2, int reverse);void GEOMETRYCOMMANDAPI CreateFace(char* edges,char* name, int editId);void GEOMETRYCOMMANDAPI CreateChamfer(char* edges, int editId,double d1,double d2,int typeindex);void GEOMETRYCOMMANDAPI EditChamfer(int id, char*setidStr, char* indexListStr, double d1, double d2, int sym);void GEOMETRYCOMMANDAPI CreateFillet(char* edges, double rad, int editID);void GEOMETRYCOMMANDAPI CreateVariableFillet(char*edges, double basicrad, int editId, int setid, int edgeindex);void GEOMETRYCOMMANDAPI CreateBooLOperation(char* booltype, int set1, int body1, int set2, int body2);void GEOMETRYCOMMANDAPI EditBooLOperation(int id, char* booltype, int set1, int body1, int set2, int body2);void GEOMETRYCOMMANDAPI CreateMirrorFeature(char* bodys, char* method,int faceindex, int facebody,char* planemethod, double random0, double random1, double random2, double base0, double base1, double base2,char* saveori);void GEOMETRYCOMMANDAPI EditMirrorFeature(int id, char* bodys, char* method, int faceindex, int facebody, char* planemethod, double random0, double random1, double random2, double base0, double base1, double base2, char* saveori);void GEOMETRYCOMMANDAPI RotateFeature(char* body, double basicx, double basicy, double basicz, //体 & 基准点int method, int edgeBoby, int edgeIndex, double axisx, double axisy, double axisz, int reverse, //轴线 double angle, int saveOri);void GEOMETRYCOMMANDAPI EditRotateFeature(int bodyid, char* body, double basicx, double basicy, double basicz, //体 & 基准点int method, int edgeBoby, int edgeIndex, double axisx, double axisy, double axisz, int reverse, //轴线 double angle, int saveOri);void GEOMETRYCOMMANDAPI CreateMoveFeature(char * bodys, char* method,double startpt0, double startpt1, double startpt2, double endpt0, double endpt1, double endpt2, char* save,  char*reverse,double length, double dir0, double dir1, double dir2);void GEOMETRYCOMMANDAPI EditMoveFeature(int id, char * bodys, char* method, double startpt0, double startpt1, double startpt2, double endpt0, double endpt1, double endpt2, char* save, char* reverse,double length, double dir0, double dir1, double dir2);void GEOMETRYCOMMANDAPI MakeMatrix(char * bodys, int optionindex, double dir10, double dir11, double dir12, int reverse1, double dis1, int count1, int showdir2,double dir20, double dir21, double dir22, int reverse2, double dis2, int count2, double basept0, double basept1, double basept2, double axis0, double axis1, double axis2,int wirereverse, int wirecount, double degree);void GEOMETRYCOMMANDAPI EditMatrix(int id, char * bodys, int optionindex, double dir10, double dir11, double dir12, int reverse1, double dis1, int count1, int showdir2,double dir20, double dir21, double dir22, int reverse2, double dis2, int count2, double basept0, double basept1, double basept2, double axis0, double axis1, double axis2,int wirereverse, int wirecount, double degree);void GEOMETRYCOMMANDAPI CreateExtrusion(int id,char* name,char *edges,double dis,double pt0,double pt1,double pt2,char* reverse,char* solid);void GEOMETRYCOMMANDAPI CreateRevol(int id, char* name, char *edges, double basept0, double basept1, double basept2, double degree, char* optionindex, int axissetid, int edgeindex, double coor0, double coor1, double coor2, char* reverse, char* solid);void GEOMETRYCOMMANDAPI CreateLoft(int id, char* name, char* solid, char* sec);void GEOMETRYCOMMANDAPI CreateSweep(int id, char*edges, char* solid, int pathset,int pathedge);void GEOMETRYCOMMANDAPI MakeGeoSplitter(char* bodystr, char* method, int facebody, int faceid, char* planemethod, double random0, double random1, double random2, double base0, double base1, double base2);void GEOMETRYCOMMANDAPI EditGeoSplitter(int editid, char* bodystr, char* method, int facebody, int faceid, char* planemethod, double random0, double random1, double random2, double base0, double base1, double base2);void GEOMETRYCOMMANDAPI MakeFillHole(char* faces, int editID);void GEOMETRYCOMMANDAPI MakeRemoveSurface(char* faces, int editID);void GEOMETRYCOMMANDAPI CreateFillGap(char* type, int set1, int body1, int set2, int body2);void GEOMETRYCOMMANDAPI EditFillGap(int id, char*type, int set1, int body1, int set2, int body2);
}

借鉴这个例子,自己的程序也能集成Python了吧~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/185055.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语法学习】20 - 文件访问顺序

文章目录 0 前言1 文件位置指示符2 rewind()2.1 函数原型2.2 参数2.3 返回值2.4 使用说明 3 ftell()函数3.1 函数原型3.2 参数3.3 返回值 4 fseek()4.1 函数原型4.2 参数4.3 返回值 5 示例5.1 示例15.2 示例2 0 前言 C语言文件访问分为顺序文件访问和随机文件访问。 1 文件位…

云架构师学习------腾讯云通识-存储与数据库

云架构师学习------腾讯云通识-存储与数据库 云架构师学习------腾讯云通识-存储与数据库存储基础存储服务对象存储-COS产品概述功能概览产品优势 云硬盘-CBS产品概述产品功能产品优势云硬盘类型 文件存储-CFS产品概述产品功能产品优势文件存储类型及性能规格存储类型性能与规格…

react之Component存在的2个问题

问题 只要执行setState()&#xff0c;即使不改变状态数据&#xff0c;组件也会重新render()只当前组件重新render()&#xff0c;就会自动重新render子组件 原因 Component中的shouldComponentUpdate()总是返回true 思路 只有当组件的state或props数据发生改变时才重新rend…

Qt QTableView排序

1.简介 在开发过程中&#xff0c;我们需要通过点击表头来对QTableView或QTreeView等一系列高级视图进行排序操作&#xff0c;以下是进行排序的步骤。 步骤&#xff1a; 首先创建了一个QStandardItemModel对象或者继承QAbstractTableModel类作为数据模型&#xff0c;并设置了…

工厂设备扫码使用售卖联网开发需要怎么开发开源代码?

我们将详细介绍如何使用开源代码开发一套用于工厂设备联网统计的系统。我们将详细讨论所需硬件组件的选择、开源框架和库的使用、软件开发流程以及最后的集成和部署。在这个过程中&#xff0c;我们将提供实用的操作步骤和指导&#xff0c;帮助你更容易地完成这个复杂的任务。 …

Docker实战

一、Docker安装 以下均以CentOS 7为例 1、安装Docker yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2、启动和校验 # 启动Docker systemctl start docker# 停止Docker systemctl stop docker# 重启 systemctl resta…

【Qt之QVariant】使用

介绍 QVariant类类似于最常见的Qt数据类型的联合。由于C禁止联合类型包括具有非默认构造函数或析构函数的类型&#xff0c;大多数有趣的Qt类不能在联合中使用。如果没有QVariant&#xff0c;则QObject::property()和数据库操作等将会受到影响。 QVariant对象同时持有一个单一…

【数据结构】树与二叉树(六):二叉树的链式存储

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语5.1.4 树的表示 5.2 二叉树5.2.1 二叉树1. 定义2. 特点3. 性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉…

从业务到软件架构——软件建模

一、问题 1.架构到底是什么&#xff1f;架构和业务之间到底什么关系&#xff1f; 2.好的架构的设计出发点是什么&#xff1f;好的架构应该是什么样的&#xff1f; 作为一个计算机领域的词汇&#xff0c;架构的定义是&#xff1a;有关软件整体结构与组件的抽象描述&#xff0c…

PHP代码示例

我们需要使用PHP的curl库来发送HTTP请求。以下是一个基本的示例&#xff1a; php <?php // 初始化curl $ch curl_init(); // 设置代理 curl_setopt($ch, CURLOPT_PROXY, ""); // 设置URL curl_setopt($ch, CURLOPT_URL, ""); // 执行请求 $respon…

C语言--分段函数--switch语句

如何用switch语句写分段函数呢&#xff1f;⭐️ 首先介绍一下switch语句的语法规则⭐️ switch(整形表达式) {case 常量表达式1&#xff1b; //标签必须唯一语句块1;break;case 常量表达式2&#xff1b; //if(a0),而case中时系统自动加语句块2&#xff1b;break&#xff1b;c…

台式电脑一键重装Win10系统详细教程

很多用户都在使用台式Win10电脑办公&#xff0c;如果电脑出现系统问题无法解决了&#xff0c;这时候就可以考虑给电脑重装系统哦&#xff0c;下面小编给大家详细介绍关于台式电脑一键重装Win10系统的步骤方法&#xff0c;安装后电脑就能恢复正常&#xff0c;也不会影响到用户的…

浅谈电力物联网时代物联网技术在电力系统中的应用

贾丽丽 安科瑞电气股份有限公司 上海嘉定201801 摘要&#xff1a;在电力系统建设中&#xff0c;物联网的应用不仅促进了我国电力工业的发展&#xff0c;而且对我国的物联网技术也起到了一定的促进作用。随着物联网技术应用于电力系统&#xff0c;推动了中国工业的快速发展。因…

Java 设计模式——外观模式

目录 1.概述2.结构3.实现3.1.子系统类3.2.外观类3.3.测试 4.优缺点5.使用场景6.源码解析 1.概述 &#xff08;1&#xff09;有些人可能炒过股票&#xff0c;但其实大部分人都不太懂&#xff0c;这种没有足够了解证券知识的情况下做股票是很容易亏钱的&#xff0c;刚开始炒股肯…

CSS 滚动捕获 Scroll Snap

CSS 滚动捕获 Scroll Snap CSS 滚动捕获允许开发者通过声明一些位置(或叫作捕获位置)来创建精准控制的滚动体验. 通常来说轮播图就是这种体验的例子, 在轮播图中, 用户只能停在图 A 或者图 B, 而不能停在 A 和 B 的中间. 比如平时用淘宝或小红书, 当你上滑到下一个推荐内容时…

MySQL json相关函数详解

MySQL提供了一系列的JSON函数&#xff0c;用于解析、提取、修改和操作JSON数据。以下是一些常用的JSON函数及其功能。 以下所有操作都使用该表&#xff08;zone_test&#xff09;用来演示&#xff1a; 一&#xff1a;JSON_OBJECT(key1,value1,key2,value2) 1、作用&#xff1a;…

json数据格式的理解(前+后)

什么是JSON&#xff1a; JSON&#xff08;JavaScript Object Notation&#xff09;是一种广泛使用的数据交换格式&#xff0c;它在前端和后端开发中都扮演着重要的角色。 JSON 的结构&#xff1a; JSON 数据由大括号 {} 包围&#xff0c;表示对象。 对象中的数据以键值对形式…

【C/PTA】循环结构进阶练习(三)

本文结合PTA专项练习带领读者掌握循环结构&#xff0c;刷题为主注释为辅&#xff0c;在代码中理解思路&#xff0c;其它不做过多叙述。 文章目录 7-1 循环-Fibonacci数列的运算7-2 循环-找数字7-3 循环-小智的捕食计划7-4 循环-抱大腿7-5 循环-跳&#xff01;7-6 循环-生气的峰…

Docker学习——⑤

文章目录 1、什么是Docker Container&#xff08;容器&#xff09;2、容器的生命周期2.1 容器 OOM2.2 容器异常退出2.3 容器暂停 3、容器命令详解4、容器操作案例4.1 容器批量处理技巧4.2 容器交互模式4.3 容器自动重启4.4 容器环境变量配置 5、综合实战5.1 Mysql 容器化安装5.…

〔003〕虚幻 UE5 基础教程和蓝图入门

✨ 目录 ▷ 新建项目▷ 快捷操作▷ 镜头移动速度▷ 新建蓝图关卡▷ 打印字符串▷ 蓝图的快捷键▷ 场景中放置物体▷ 通过蓝图改变物体位置▷ 展现物体运动轨迹▷ 队列运行▷ 新建项目 打开虚幻启动程序,选择 引擎版本 后点击 启动选择 游戏 类型,默认设置中选择 蓝图,项目名…