C++ 项目:使用 GSL 数学运算库 C++ 调用Python

文章目录

  • Part.I Introduction
    • Chap.I CMakeLists
    • Chap.II ExportLibGSL.h
    • Chap.III test_python.cpp
  • Part.II GSL 使用方法
  • Part.III C++ 调用 Python 使用方法
  • 相关博客

Part.I Introduction

本文是一个项目的使用教程,此项目是一个使用 GSL 的小项目,还有 C++ 调用 Python。项目虽简单,但麻雀虽小五脏俱全,笔者觉得此项目架构还是比较明晰的,值得一看。

在这里插入图片描述

项目所包含文件如下:

.
 ─app_test
│  ├─TEMP_TestGSL
│  └─TEMP_TestPython
├─LibGSL
│  ├─example
│  └─gexport
├─LibPython
│  ├─example
│  │  └─__pycache__
│  └─gexport
└─_doc

请戳我下载,下面展示部分文件


Chap.I CMakeLists

下面是一个主 CMakeLists。

# 要求的 CMAKE 最低版本号
cmake_minimum_required(VERSION 3.0.0)
# 项目名和版本号  
project(Temp VERSION 1.0.0)
# information message

# 编译器设置
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)

# 编译选项设置
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
    SET(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}_Windows)
    add_compile_options(/bigobj)
    add_compile_options(/MP)
    add_compile_options(/w)
endif()

if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -pthread")
else()
    message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

# Choose different compilation configurations according to VS compilation
# 根据VS编译选择不同的编译配置
if(CMAKE_BUILD_TYPE MATCHES "Release")
    set(CMAKE_BUILD_POSTFIX "${CMAKE_RELEASE_POSTFIX}")
elseif(CMAKE_BUILD_TYPE MATCHES "Debug")
    set(CMAKE_BUILD_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
elseif(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
    set(CMAKE_BUILD_POSTFIX "${CMAKE_RELWITHDEBINFO_POSTFIX}")
elseif(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
    set(CMAKE_BUILD_POSTFIX "${CMAKE_MINSIZEREL_POSTFIX}")
else()
    set(CMAKE_BUILD_POSTFIX "")
endif()

# Set the ROOT and subdirectory, you should put the CMakeList.txt in these file directories
# 设置根目录和子目录时,应将CMakeList.txt文件在这些文件目录中
set(ROOT ${PROJECT_SOURCE_DIR})
set(EXECUTABLE_OUTPUT_PATH ${BUILD_DIR}/Bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BUILD_DIR}/Bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BUILD_DIR}/Lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BUILD_DIR}/Lib)

set(CMAKE_DEBUG_POSTFIX "d")
set(CMAKE_RELEASE_POSTFIX "")
set(CMAKE_RELWITHDEBINFO_POSTFIX "rd")
set(CMAKE_MINSIZEREL_POSTFIX "s")


# 为调试Cmake输出消息
message(STATUS "operation system is : ${CMAKE_SYSTEM}")
message(STATUS "current platform is : ${CMAKE_SYSTEM_NAME}")
message(STATUS "CMake version    is : ${CMAKE_SYSTEM_VERSION}")
message(STATUS "C compiler       is : ${CMAKE_C_COMPILER}")
message(STATUS "C++ compiler     is : ${CMAKE_CXX_COMPILER}")
message(STATUS "Build directory  is : ${BUILD_DIR}")
message(STATUS "The program main directory is : ${ROOT}")



# 设置一些文件夹,库里面的 CMake 会用到
set(file_fold 
    example gexport
    )
set(PrintFile FALSE)


# ==================================================================================
# 为了测试 Python,各位不用开即可
option(Main_USE_PYTHON    "using "  OFF)

# 链接三方库
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
    #For windows
    # ==============================================================================
    if (NOT DEFINED Third_GSL_ROOT)
        find_path(Third_GSL_ROOT         HINTS "${Third_GSL_ROOT}"          "$ENV{Third_GSL_ROOT}            ")
    endif()
    # ==============================================================================
endif()


set(LibGSL              LibGSL)
set(LibGSLSrc           ${ROOT}/${LibGSL})
add_subdirectory(${LibGSLSrc}       ${BUILD_DIR}/${LibGSL})
SET_PROPERTY(TARGET ${LibGSL}       PROPERTY FOLDER "LIB")


if(Main_USE_PYTHON)
    set(LibPython             LibPython)
    set(LibPythonSrc          ${ROOT}/${LibPython})
    add_subdirectory(${LibPythonSrc}      ${BUILD_DIR}/${LibPython})
    SET_PROPERTY(TARGET ${LibPython}      PROPERTY FOLDER "LIB")
endif()

# 使用文件夹选项打开
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON) 

Chap.II ExportLibGSL.h

#ifndef EXPORT_LibGSL_H
#define EXPORT_LibGSL_H

#if defined(_MSC_VER)
#pragma warning(disable : 4244)
#pragma warning(disable : 4251)
#pragma warning(disable : 4275)
#pragma warning(disable : 4512)
#pragma warning(disable : 4267)
#pragma warning(disable : 4702)
#pragma warning(disable : 4511)
#pragma warning(disable : 4996)
#endif

#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BCPLUSPLUS__) || defined(__MWERKS__)
#if defined(TEMP_LibGSL_LIBRARY)
#define LibGSL_LIBRARY_EXPORT __declspec(dllexport)
#else
#define LibGSL_LIBRARY_EXPORT __declspec(dllimport)
#endif
#else
#define LibGSL_LIBRARY_EXPORT
#endif

#ifdef _MSC_VER
#if (_MSC_VER >= 1300)
#define __STL_MEMBER_TEMPLATES
#endif
#endif

#include <string>
#include <vector>
using namespace std;

#ifndef SIZE_INT
#define SIZE_INT sizeof(int)
#endif

#ifndef SIZE_DBL
#define SIZE_DBL sizeof(double)
#endif // !SIZE_DBL
#endif

Chap.III test_python.cpp

C++ 调用 Python 的主要代码

#include <iostream>
#include "test_python.h"

using namespace std;

namespace temp
{
    t_test_python::t_test_python() { }

    t_test_python::~t_test_python()
    {

    }

    int t_test_python::_pythonInit() {
        Py_Initialize();
        int ret = Py_IsInitialized();
        if (ret == 0) {
            cout << "Py_Initialize error" << endl;
            return kError;
        }
        return kSuccess;
    }


    void t_test_python::_pythonCleanup() {
        Py_Finalize();
    }


    int t_test_python::_callPythonAdd(PyObject* module, int a, int b) {
        //获取模块字典属性
        PyObject* pDict = PyModule_GetDict(module);
        if (pDict == nullptr) {
            PyErr_Print();
            std::cout << "PyModule_GetDict error" << std::endl;
            return kError;
        }

        //直接获取模块中的函数
        PyObject* addFunc = PyDict_GetItemString(pDict, "add");
        if (addFunc == nullptr) {
            std::cout << "PyDict_GetItemString 'add' not found" << std::endl;
            return kError;
        }

        // 构造python 函数入参, 接收2
        // see: https://docs.python.org/zh-cn/3.7/c-api/arg.html?highlight=pyarg_parse#c.PyArg_Parse
        PyObject* pArg = Py_BuildValue("(i,i)", a, b);

        //调用函数,并得到 python 类型的返回值
        PyObject* result = PyEval_CallObject(addFunc, pArg);

        int ret = 0;
        //将python类型的返回值转换为c/c++类型
        PyArg_Parse(result, "i", &ret);
        return ret;
    }


    PyObject* t_test_python::_pythonImportModule(const char* pyDir, const char* name) {
        // 引入当前路径,否则下面模块不能正常导入
        char tempPath[256] = {};
        sprintf(tempPath, "sys.path.append('%s')", pyDir);
        PyRun_SimpleString("import sys");
        //PyRun_SimpleString("sys.path.append('./')");
        PyRun_SimpleString(tempPath);
        PyRun_SimpleString("print('----------------------------------------')");
        PyRun_SimpleString("print('curr sys.path: ', sys.path)");
        PyRun_SimpleString("print('----------------------------------------')");
        // import ${name}
        PyObject* module = PyImport_ImportModule(name);
        if (module == nullptr) {
            PyErr_Print();
            cout << "PyImport_ImportModule '" << name << "' not found" << endl;
            return nullptr;
        }

        return module;
    }


    int t_test_python::_callPythonGetName(PyObject* module, std::string firstName, std::string& outName) {
        //获取模块字典属性
        PyObject* pDict = PyModule_GetDict(module);
        if (pDict == nullptr) {
            PyErr_Print();
            std::cout << "PyModule_GetDict error" << std::endl;
            return kError;
        }

        //直接获取模块中的函数
        PyObject* addFunc = PyDict_GetItemString(pDict, "get_name");
        if (addFunc == nullptr) {
            std::cout << "PyDict_GetItemString 'add' not found" << std::endl;
            return kError;
        }

        // 构造python 函数入参, 接收2
        // see: https://docs.python.org/zh-cn/3.7/c-api/arg.html?highlight=pyarg_parse#c.PyArg_Parse
        PyObject* pArg = Py_BuildValue("(s)", firstName.c_str());

        //调用函数,并得到python类型的返回值
        PyObject* result = PyEval_CallObject(addFunc, pArg);

        char* name = nullptr;
        //将python类型的返回值转换为c/c++类型
        PyArg_Parse(result, "s", &name);

        char tempStr[256] = {};
        int strLen = strlen(name);
        if (strLen > 256) {
            return kError;
        }
        strcpy(tempStr, name);
        outName = tempStr;
        return kSuccess;
    }


    int t_test_python::processBatch()
    {
        _pythonInit();

        //直接运行 python 代码
        PyRun_SimpleString("print('---------- Hello Python form C/C++ ----------')");
        PyRun_SimpleString("print('Test BEGIN ...')");
        //调用 Python 脚本
        PyObject* helloModule = _pythonImportModule("A:/aWork/scripts/AURORA/V1/LibPython/example", "hello");    // 这里最好还是给绝对路径吧
        if (helloModule == nullptr) {
            return -1;
        }

        // call python add function
        int result = _callPythonAdd(helloModule, 1, 3);
        cout << "1 + 3 = " << result << endl;

        // call python get_name function
        std::string fullName;
        _callPythonGetName(helloModule, "Summer", fullName);
        cout << fullName << endl;
        PyRun_SimpleString("print('Test END!')");
        _pythonCleanup();
    }
}

Part.II GSL 使用方法

首先需要安装 CMake、VS Studio

为了防止不必要的歧义,下面将项目的根目录称为『当前目录』

首先将_doc文件夹下的gsl.zip解压,放到一个你不常动的目录中,将这个目录(或 这个目录/gsl)称为『gsl目录』,懂我意思吧

1、在当前目录下新建 build 文件夹

2、打开 CMake,源码路径设置为当前目录,build 路径设置为 当前目录/build

3、点击 Configure,之后配置根据自己实际情况配,配好点击 Finish

在这里插入图片描述

4、会报错,不要急,把 gsl 目录赋给 Third_GSL_ROOT,再次点击Configure

在这里插入图片描述

5、依次点击GenerateOpen Project,打开项目

6、将 TEMP_TestGSL 设为启动项目

在这里插入图片描述

7、快捷键 F5 运行,得到结果

在这里插入图片描述

完事!

Part.III C++ 调用 Python 使用方法

1、上面第三步勾选 Main_USE_PYTHON,把 Python 的路径给它

2、依次点击ConfigureGenerateOpen Project,打开项目

3、将 TEMP_TestPython 设为启动项目

在这里插入图片描述

4、快捷键 F5 运行,得到结果
在这里插入图片描述

完事!

相关博客

  • C/C++ 之 GSL 数学运算库使用笔记
  • Windows 下用 C++ 调用 Python

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Solana 线下活动回顾|多方创新实践,引领 Solana“文艺复兴”新浪潮

Solana 作为在过去一年里实现突破式飞跃的头部公链&#xff0c;究竟是如何与 Web3 行业共振&#xff0c;带来全新的技术发展与生态亮点的呢&#xff1f;在 3 月 24 日刚结束的「TinTin Destination Moon」活动现场&#xff0c;来自 Solana 生态的的专家大咖和 Web3 行业的资深人…

基于lora技术微调Gemma(2B)代码实践

一、前置条件 获得模型访问权&#xff0c;选择Colab运行时&#xff0c;配置训练环境。 先在Kaggle上注册&#xff0c;然后获得Gemma 2B 的访问权&#xff1b; 然后在Google colab 配置环境&#xff0c;主要是GPU的选择&#xff0c;免费的是T4&#xff0c;建议采用付费的A100…

【Linux】详解动静态库的制作和使用动静态库在系统中的配置步骤

一、库的作用 1、提高开发效率&#xff0c;让开发者所有的函数实现不用从零开始。 2、隐藏源代码。 库其实就是所有的.o文件用特定的方式进行打包形成一个文件&#xff0c;各个.o文件包含了源代码中的机器语言指令。 二、动态库和静态库的制作和使用 2.1、静态库的制作和使用…

DTFT及其反变换的直观理解

对于离散时间傅里叶变换(DTFT)及其反变换的讲解&#xff0c;教材里通常会先给出DTFT正变换的公式&#xff0c;再举个DTFT的简单变换例子&#xff0c;推导一下DTFT的性质&#xff0c;然后给出DTFT反变换的公式&#xff0c;再证明一下正变换和反变化的对应关系。总的来说就是&…

波士顿房价预测案例(python scikit-learn)---多元线性回归(多角度实验分析)

波士顿房价预测案例&#xff08;python scikit-learn&#xff09;—多元线性回归(多角度实验分析) 这次实验&#xff0c;我们主要从以下几个方面介绍&#xff1a; 一、相关框架介绍 二、数据集介绍 三、实验结果-优化算法对比实验&#xff0c;数据标准化对比实验&#xff0…

南京观海微电子---Vitis HLS的工作机制——Vitis HLS教程

1. 前言 Vitis HLS&#xff08;原VivadoHLS&#xff09;是一个高级综合工具。用户可以通过该工具直接将C、 C编写的函数翻译成HDL硬件描述语言&#xff0c;最终再映射成FPGA内部的LUT、DSP资源以及RAM资源等。 用户通过Vitis HLS&#xff0c;使用C/C代码来开发RTL IP核&#x…

大疆御Pro(一代)更换晓spark摄像头评测

御Pro是17年的老机器&#xff0c;除了摄像头有点拉跨&#xff0c;续航、抗风、操作性在大疆民用系列里面算是数得上的。 机缘巧合&#xff0c;手头有几个御的空镜头&#xff08;里面的芯片已经去掉了&#xff09;&#xff0c;还有几个晓的摄像头&#xff08;只有芯片&#xff0…

Java基础入门--面向对象课后题(2)

文章目录 1 Employee2 SalariedEmployee3 HourlyEmployee4 SalesEmployee5 BasePlusSalesEmployee6 测试类 Example177 完整代码 某公司的雇员分为5类&#xff0c;每类员工都有相应的封装类&#xff0c;这5个类的信息如下所示。 (1) Employee&#xff1a;这是所有员工总的父类。…

网站可扩展架构设计——领域驱动设计(下)

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、架构设计简述 1.经典分层图 DDD分层架构的重要原则&#xff1a;每层只能与位于其下方的层发生耦合 User Interface —— 接口/用户界面层。提…

linux0.11中jmpi 0,8解析

系统在执行该行代码时已经为保护模式, jmpi 0,8会将段选择子(selector)载入cs段寄存器&#xff0c;并计算出逻辑地址。 段选择子的结构如下&#xff1a; 段选择子包括三部分&#xff1a;描述符索引&#xff08;index&#xff09;、TI、请求特权级&#xff08;RPL&#xff09;。…

拯救者Legion R9000X 2021(82HN)原装出厂Win10系统镜像ISO下载

lenovo联想拯救者笔记本R9000X 2021款原厂Windows10系统安装包&#xff0c;恢复出厂开箱状态预装OEM系统 链接&#xff1a;https://pan.baidu.com/s/1tx_ghh6k0Y9vXBz-7FEQng?pwd7mih 提取码&#xff1a;7mih 原装出厂系统自带所有驱动、出厂主题壁纸、系统属性联机支持标…

《QT实用小工具·十》本地存储空间大小控件

1、概述 源码放在文章末尾 本地存储空间大小控件&#xff0c;反应电脑存储情况&#xff1a; 可自动加载本地存储设备的总容量/已用容量。进度条显示已用容量。支持所有操作系统。增加U盘或者SD卡到达信号。 下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #if…

2024 蓝桥打卡Day31

递归与辗转相除法 递归&#xff08;Recursion&#xff09;辗转相除法&#xff08;Euclidean Algorithm&#xff09;总结 递归&#xff08;Recursion&#xff09; 递归是指一个函数在执行过程中调用自身的过程。在编程中&#xff0c;递归函数在遇到满足某个条件时会停止调用自身…

Servlet原理Servlet API

目录 一、Servlet运行原理 1.1、问题 1.2、Servlet的具体执行过程 1.3、Tomcat初始化流程小结 1.4、Tomcat处理请求流程 二、Servlet API详解 2.1、HttpServlet类 2.1.1、处理Get请求 2.2、HttpServletRequest类 2.3、HttpServletResponse类 2.3.1、设置状态码 ​2.…

wsl.conf在windows的什么路径

结论 全局的.wslconfig找不到。 局部的wsl.conf在ubuntu中的/etc/wsl.conf。 官网 https://learn.microsoft.com/zh-cn/windows/wsl/wsl-config .wslconfig 使用 .wslconfig 为 WSL 上运行的所有已安装的发行版配置全局设置。 默认情况下&#xff0c;.wslconfig 文件不存在。…

Hadoop MapReduce

MapReduce分为两个阶段&#xff0c;分为Map阶段和Reduce阶段&#xff0c;可以自定义map函数和reduce函数&#xff0c; map函数的输入是行在文件的字节偏移量&#xff0c;value是文件的一行数据。 reduce函数的输入是key和对应key的value组&#xff0c;然后reduce函数可以对这…

【Linux】SSH协议应用

SSH协议 SSH简介实现OpenSSH ssh中的四个文件~/.ssh文件路径实验解析 SSH 简介 SSH&#xff08;secure shell&#xff09;只是一种协议&#xff0c;存在多种实现&#xff0c;既有商业实现&#xff0c;也有开源实现。本文针对的实现是OpenSSH&#xff0c;它是自由软件&#xf…

面试题:RabbitMQ 消息队列中间件

1. 确保消息不丢失 生产者确认机制 确保生产者的消息能到达队列&#xff0c;如果报错可以先记录到日志中&#xff0c;再去修复数据持久化功能 确保消息未消费前在队列中不会丢失&#xff0c;其中的交换机、队列、和消息都要做持久化消费者确认机制 由spring确认消息处理成功后…

字符分类函数

字符分类函数 C语言中有⼀系列的函数是专门做字符分类的&#xff0c;也就是⼀个字符是属于什么类型的字符的。这些函数的使用都需要包含⼀个头文件是 ctype.h 这些函数的使用方法非常类似&#xff0c;我们就讲解⼀个函数的事情&#xff0c;其他的非常类似&#xff1a; int i…

蓝桥杯速成5-AD/DA模数转换

一、原理图 上图可知该芯片使用的是iic时序&#xff0c;而不是51单片机的xpt2046时序&#xff0c;iic我们都很熟悉了吧 并且大赛还提供了我们iic底层驱动代码 左上角有AIN0-4四个转换输入通道&#xff0c;和AOUT一个输出通道&#xff0c;由控制字节选择 地址字节&#xff1a;0x…