Python通过Ctypes调用C++类,实测有效

文章目录

  • 前言
  • 创建vs dll工程
  • 添加外部库
  • 编辑代码
  • 编译
  • 测试
  • 参考

前言

在软件开发中,有时候需要Python与C++相结合,以充分发挥两者的优势 。Python作为一种高级编程语言,具有简洁易读的特点,适用于快速开发和原型设计。而C++则是一种性能强大的编程语言,适用于需要高效率和底层控制的场景。

Python调用C++代码的主要方式是使用Cython、ctypes或SWIG等工具 。其中,Cython是一种混合语言,允许将Python代码与C语言结合,通过编写类型声明来提高性能。而ctypes是Python标准库中的一部分,允许Python直接调用C函数,并处理C数据类型。另外,SWIG(Simplified Wrapper and Interface Generator)是一个自动生成Python和其他语言之间的接口代码的工具,使Python可以调用C++代码。

在实际应用中,Python调用C++的场景包括但不限于:加速Python程序的关键部分、调用现有的C++库以利用其功能、优化某些算法以提高性能等。通过将Python与C++相结合,开发人员可以在保持Python代码易读性和开发效率的同时,充分发挥C++的性能优势,实现更加复杂和高效的应用程序。

Python通过ctypes调用C++代码是一种常见的技术,它提供了一种简单而直接的方法,让Python与C++进行交互。ctypes是Python标准库的一部分,允许Python代码调用动态链接库(DLL)中的C函数,并处理C数据类型。虽然ctypes主要设计用于调用C函数,但也可以用于调用C++代码,只需注意一些特殊的注意事项。

要在Python中通过ctypes调用C++代码,首先需要确保将C++代码编译为动态链接库,以便Python能够加载并调用其中的函数。然后,需要在Python中定义与C++函数相对应的函数原型,并在调用时传递正确的参数和返回类型。此外,需要注意C++代码中的名称修饰(name mangling)以及C++异常处理等问题,确保与Python的交互能够顺利进行。

在实际应用中,Python通过ctypes调用C++代码的场景包括但不限于:利用现有的C++库实现特定功能、加速Python程序的关键部分、与C++库进行交互以实现复杂的功能等。通过使用ctypes,开发人员可以在Python中利用C++的性能优势,同时保持Python代码的简洁性和易读性。

然而,虽然ctypes提供了一种方便的方法来调用C++代码,但它并不是最高效的方法,特别是对于复杂的数据结构和函数签名而言。对于更复杂的场景,可以考虑使用Cython或SWIG等工具,它们提供了更强大和灵活的功能,以便更好地集成Python和C++代码。

因此,Python通过ctypes调用C++代码是一种简单而有效的方法,适用于许多场景。通过正确地处理数据类型和函数签名,并注意到C++与Python之间的差异,开发人员可以轻松地在两种语言之间进行交互,实现更加强大和灵活的应用程序。

创建vs dll工程

在这里插入图片描述

在这里插入图片描述

添加外部库

参考:
vs2019添加使用外置库的设置

编辑代码

添加自己写的C++类

在这里插入图片描述

Foo.h

#pragma once
#ifndef _pro_header_  
#define _pro_header_ 

#ifdef EXPORT_PRO_DLL //如果引用此头文件有预定义为 EXPORT_PRO_DLL
#define PRO_API __declspec(dllexport)  
#else  
#define PRO_API __declspec(dllimport)  
#endif  


class Foo
{
public:
    Foo(int n);
    ~Foo();
    void bar();
    int foobar(int n);
private:
    int val;
};

extern "C"
{
    PRO_API Foo* Foo_new(int n);
    PRO_API void Foo_bar(Foo* foo);
    //PRO_API int* Foo_foobar(Foo* foo, int n); //int、short等不能返回地址类型,因为Python那边不允许;只有char类型才需要使用地址类型
    PRO_API int Foo_foobar(Foo* foo, int n);

    PRO_API void del_Foo(Foo* foo);
}

#endif 

Foo.cpp

#define EXPORT_PRO_DLL

#include "pch.h"
#include "Foo.h"

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

using namespace std;

Foo::Foo(int n)
{
    this->val = n;
}
void Foo::bar()
{
    std::cout << "Value is " << this->val << std::endl;
}
Foo::~Foo()
{
    cout << "delete foo" << endl;
}

int Foo::foobar(int n)
{
    int* data = new int[2];
    data[0] = 1 + n;
    data[1] = 2 + n;
    return *data;
}

void del_Foo(Foo* foo)
{
    delete foo;
}

Foo* Foo_new(int n)
{
    return new Foo(n);
}

void Foo_bar(Foo* foo)
{
    foo->bar();
}

int Foo_foobar(Foo* foo, int n) {
    return foo->foobar(n);
}

编译

在这里插入图片描述

测试

from ctypes import *

lib = cdll.LoadLibrary(r"路径\x64\Debug\Foo.dll")

class Foo(object):
    def __init__(self, n):
        lib.Foo_new.argtypes = [c_int]
        lib.Foo_new.restype = c_void_p
        lib.Foo_bar.argtypes = [c_void_p]
        lib.Foo_bar.restype = c_void_p
        lib.Foo_foobar.argtypes = [c_void_p, c_int]
        lib.Foo_foobar.restype = c_int

        lib.del_Foo.argtypes = [c_void_p]
        lib.del_Foo.restype = c_void_p

        self.obj = lib.Foo_new(n)

    def __del__(self):
        lib.del_Foo(self.obj)


    def bar(self):
        lib.Foo_bar(self.obj)

    def foobar(self, n):
        return lib.Foo_foobar(self.obj, n)

if __name__ == '__main__':
    f = Foo(5)
    print(f.bar())
    print(f.foobar(5))

在这里插入图片描述

Ctypes类型

注意:只有字符串类型或者自定义类型才需要地址类型来实现数据传递,其他数据看下表。

在这里插入图片描述

参考

Python调用C/C++的两种方法

官方:扩展和嵌入 Python 解释器

【知识分享】C++与Python联合编程(上)

【知识分享】C++与Python联合编程(下)

Tip:用数据类型的视角去看C++的类,那么类中的方法或者属性可以看成函数中的函数。

使用ctypes在Python中调用C++动态库

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

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

相关文章

小程序绕过 sign 签名

之前看到了一篇文章【小程序绕过sign签名思路】之前在做小程序渗透时也遇到了这种情况&#xff0c;但是直接放弃测试了&#xff0c;发现这种思路后&#xff0c;又遇到了这种情况&#xff0c;记录下过程。 并没有漏洞分享&#xff0c;仅仅是把小程序也分享出来&#xff0c;方便…

上位机图像处理和嵌入式模块部署(qmacvisual轮廓查找)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;图像的处理流程一般都是这样的&#xff0c;即灰度化-》降噪-》边缘检测-》二值化-》开闭运算-》轮廓检测。虽然前面的几个…

AI开源概览及工具使用

一、前言 随着ChatGPT热度的攀升&#xff0c;越来越多的公司也相继推出了自己的AI大模型&#xff0c;如文心一言、通义千问等。各大应用也开始内置AI玩法&#xff0c;如抖音的AI特效&#xff1b; 关联资源&#xff1a;代码 GitHub、相关论文、项目Demo、产品文档、Grok Ai、gr…

多数据源 - dynamic-datasource | 进阶 - 动态添加、移除数据源

文章目录 实现原理示例程序🗯️ 上节回顾:前节中,了解了 dynamic-datasource 的事务支持。 👉 本节目标:了解 dynamic-datasource 的进阶用法 - 动态添加/移除数据源。 动态添加/移除数据源:指在系统运行过程中动态的添加数据源,删除数据源,多使用于基于数据库的多租…

探讨苹果 Vision Pro 的空间视频(术语辨析、关键技术、思考)

背景:一位资深视频技术从业者在 Pixvana 工作,积累了丰富的捕获、处理、编码、流传和播放空间媒体经验。 一、术语 空间视频:传统的 3D 视频,呈矩形,包含左右眼视图,如 iPhone15 Pro 和 Vision Pro 可录制。沉浸式视频:非矩形的环绕式视频体验,通常由两个或多个传感器…

【C++】仿函数优先级队列反向迭代器

目录 一、优先级队列 1、priority_queue 的介绍 2、priority_queue 的使用 3、 priority_queue 的模拟实现 1&#xff09;priority_queue()/priority_queue(first, last) 2&#xff09;push&#xff08;x&#xff09; 3&#xff09;pop&#xff08;&#xff09; 4&#…

Datawhale 零基础入门数据挖掘-Task1 赛题理解

一、 赛题理解 Tip:此部分为零基础入门数据挖掘的 Task1 赛题理解 部分&#xff0c;为大家入门数据挖掘比赛提供一个基本的赛题入门讲解&#xff0c;欢迎后续大家多多交流。 赛题&#xff1a;零基础入门数据挖掘 - 二手车交易价格预测 地址&#xff1a;零基础入门数据挖掘 -…

【Vue】三、使用ElementUI实现图片上传

目录 一、前端代码实现 二、后端代码实现 三、调试效果实现 一、前端代码实现 废话不多说直接上代码 <el-form-item prop"image" label"上传图片" v-model"form.image"><el-upload:action"http://localhost:8…

关于vuex 的模块开发和使用

1、文件结构 2、modules 文件内容 例子&#xff1a; ccc.js 文件内容如下&#xff1a; // 基础配置项 const state {aa: [] }const mutations {setaa (state, data) {state.aa data} }const actions {} export default {namespaced: true, state,mutations,actions } **注…

【Linux】进程通信

目录 一、管道通信 二、共享内存 三、消息队列 一、管道通信 管道是由操作系统维护的一个文件&#xff0c;管道通信的本质就是将管道文件作为临界资源&#xff0c;实现不同进程之间的数据读写&#xff0c;但是管道只允许父子进程或者兄弟进程之间的通信。 管道文件本身是全…

Redis面试题以及答案

1. 什么是Redis&#xff1f;它主要用来什么的&#xff1f; Redis&#xff0c;英文全称是Remote Dictionary Server&#xff08;远程字典服务&#xff09;&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并…

虹科Pico汽车示波器 | 免拆诊断案例 | 2019 款东风悦达起亚K2车怠速起停系统工作异常

一、故障现象 一辆2019款东风悦达起亚K2车&#xff0c;搭载G4FG发动机&#xff0c;累计行驶里程约为9 400 km。车主反映&#xff0c;行驶至路口停车等红灯时&#xff0c;怠速起停&#xff08;ISG&#xff09;系统自动使发动机熄火&#xff0c;接着组合仪表提示“怠速起停已解除…

HarmonyOS/OpenHarmony应用开发-DevEco Studio 在MAC上启动报错

报错截图 报错详细内容 ------------------------------------- Translated Report (Full Report Below) -------------------------------------Process: devecostudio [8640] Path: /Applications/DevEco-Studio.app/Contents/MacOS/devecos…

【pip 安装pymssql报错】 Failed to build pymssql

在使用pip install pymssql安装pymssql时报如下图的错误&#xff1b; 报错截图 2&#xff09;查找资料说pip<3.0版本 &#xff0c;我也试了&#xff0c;不行。 你们也可以试一试&#xff1a;pip install"pymssql<3.0" 3&#xff09;我的成功方式&#xff1…

选择word中的表格VBA

打开开发工具 选择Visual Basic插入代码 Sub 选择word中的表格() Dim t As Table an MsgBox("即将选择选区内所有表格&#xff0c;若无选区&#xff0c;则选择全文表格。", vbYesNo, "提示") If an - 6 Then Exit Sub Set rg IIf(Selection.Type wdSel…

【C++】线程库

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;C 前言 C11标准引入了线程库&#xff0c;通过其可以在C程序中方便地创建和管理线程。以下是一些常用的线程库组件&#xff1a; std::thread&#xff1a;std…

【Linux第三课-基础开发工具的使用】yum、vim、gcc/g++编译器、gdb、Make/Makefile编写、进度条程序、git命令行简单操作

目录 yum - 软件包管理器快速认识yum快速使用yumyum搜索yum安装yum卸载 yum的周边 - yum的整个生态问题 vim快速介绍vimvim的模式命令模式插入模式低行模式 常见模式 -- 命令、低行命令模式 -- 光标的移动命令模式 -- 复制粘贴、剪贴、删除命令模式 -- 小写/大写替换模式命令模…

单片机-- 数电(3)

编码器与译码器 译码 &#xff1a;将二进制代码转化为其他进制的代码 编码 &#xff1a;就是将其他代码转换为二进制码 编码器的类型 1二进制编码器 用n位二进制数码对2的n次方个输入信号进行编码的电路 2二-十进制编码器 将0到9十个十进制数转化为二进制代码的电路 2…

PyTorch 深度学习(GPT 重译)(三)

六、使用神经网络拟合数据 本章内容包括 与线性模型相比&#xff0c;非线性激活函数是关键区别 使用 PyTorch 的nn模块 使用神经网络解决线性拟合问题 到目前为止&#xff0c;我们已经仔细研究了线性模型如何学习以及如何在 PyTorch 中实现这一点。我们专注于一个非常简单…

Python 解析CSV文件 使用Matplotlib绘图

数据存储在CSV文件中&#xff0c;使用Matplotlib实现数据可视化。 CSV文件&#xff1a;comma-separated values&#xff0c;是在文件中存储一系列以‘&#xff0c;’分隔的值。 例如&#xff1a;"0.0","2016-01-03","1","3","20…