Linux下Python调用C语言

一:Python调用C语言场景

1,已经写好的C语言代码,不容易用Python实现,想直接通过Python调用写好的C语言代码

2,C比Python快(只是从语言层面,不能绝对说C程序就是比Python快)

3,想直接调用C语言丰富的库

二:Python的CTypes库

Python中调用C语言不止一种方法,常见的有:

1.SWIG,编写一个额外的接口文件来作为SWIG(终端工具)的入口

2.通过CTypes调用

3.使用Python/C API方法

但是 CTypes是最简单上手的一种,本文将用CTypes来演示如何在Python中调用C

可以先看看CTypes支持的类或者方法

>>> import ctypes
>>>
>>> dir(ctypes)
['ARRAY', 'ArgumentError', 'Array', 'BigEndianStructure', 'CDLL', 'CFUNCTYPE', 'DEFAULT_MODE', 'LibraryLoader', 'LittleEndianStructure', 'POINTER', 'PYFUNCTYPE', 'PyDLL', 'RTLD_GLOBAL', 'RTLD_LOCAL', 'SetPointerType', 'Structure', 'Union', '_CFuncPtr', '_FUNCFLAG_CDECL', '_FUNCFLAG_PYTHONAPI', '_FUNCFLAG_USE_ERRNO', '_FUNCFLAG_USE_LASTERROR', '_Pointer', '_SimpleCData', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_c_functype_cache', '_calcsize', '_cast', '_cast_addr', '_check_size', '_ctypes_version', '_dlopen', '_endian', '_memmove_addr', '_memset_addr', '_os', '_pointer_type_cache', '_reset_cache', '_string_at', '_string_at_addr', '_sys', '_wstring_at', '_wstring_at_addr', 'addressof', 'alignment', 'byref', 'c_bool', 'c_buffer', 'c_byte', 'c_char', 'c_char_p', 'c_double', 'c_float', 'c_int', 'c_int16', 'c_int32', 'c_int64', 'c_int8', 'c_long', 'c_longdouble', 'c_longlong', 'c_short', 'c_size_t', 'c_ssize_t', 'c_ubyte', 'c_uint', 'c_uint16', 'c_uint32', 'c_uint64', 'c_uint8', 'c_ulong', 'c_ulonglong', 'c_ushort', 'c_void_p', 'c_voidp', 'c_wchar', 'c_wchar_p', 'cast', 'cdll', 'create_string_buffer', 'create_unicode_buffer', 'get_errno', 'memmove', 'memset', 'pointer', 'py_object', 'pydll', 'pythonapi', 'resize', 'set_errno', 'sizeof', 'string_at', 'wstring_at']
>>>
 

其中cdll类对于我们接下来调用C非常有用处,我们通过help来查看cdll类,可以看到可以通过LoadLibrary来加载C的库(在Linux中是.so,在windows中是.dll)


三:实战

1,调用C语言的函数

首先我们在C语言中实现三个简单函数

#include<stdio.h>

void cprintf()
{
	printf("Hello word!\n");
	return;
}

int add(int a, int b)
{
	return a+b;
}

int cscanf()
{
	int a;
	int b;
	scanf("%d %d",&a,&b);
	return a+b;
}

三个函数,一个是有打印函数,一个是有传参函数,一个是有输入函数,将C编译成动态库

gcc -fPIC -c ctest.c  -o ctest.o
gcc -shared -o libctest.so ctest.o

 

然后我们在Python中调用这三个函数,

from ctypes import *

cLib = cdll.LoadLibrary('./libctest.so')

cLib.cprintf()

a = 1
b = 2
sum = cLib.add(a,b)
print(f'{a}+{b}={sum}')

cSum = cLib.cscanf()
print(f'cSum={cSum}')

 运行

可以看到运行结果与我们想要的结果一致

2,调用C语言返回值是指针的函数

C代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define uint8_t   unsigned char
#define uint16_t  unsigned short
                                                     
                                                     
typedef struct TagMyStruct
{
    char name[10];
    uint8_t age;
    int score;
} MyStruct,*MyStructPointer;
 
 
MyStructPointer cstruct_get_data_pointer() // 返回结构体指针
{
    MyStructPointer pt = (MyStructPointer)malloc(sizeof(MyStructPointer));
    strcpy(pt->name, "ftz");
    pt->age = 18;
    pt->score = 88;
    return pt;
}
 
 
MyStruct cstruct_get_data_self() // 返回结构体
{
    return (MyStruct){"csdn",100,99};
}

python调用

from ctypes import *

cLib = cdll.LoadLibrary('./cstruct.so')


class MyStruct(Structure):
    _fields_ = [
        ('name', c_char*10),
        ('age', c_ubyte),
        ('score', c_int),        
    ]
   
cLib.cstruct_get_data_self.restype = MyStruct #指定函数返回值结构体本身
dat = cLib.cstruct_get_data_self() 
print("=====get struct self from .so function=======")
print("name=",dat.name)
print("age=",dat.age)
print("score=",dat.score)
 
cLib.cstruct_get_data_pointer.restype = POINTER(MyStruct) #指定函数返回值结构体指针
dat = cLib.cstruct_get_data_pointer() 
print("=====get struct point from .so function=======")
print("name=",dat.contents.name)
print("age=",dat.contents.age)
print("score=",dat.contents.score)

运行结果

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

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

相关文章

docker配置redis插件

docker配置redis插件 运行容器redis_6390 docker run -it \ --name redis_6390 \ --privileged \ -p 6390:6379 \ --network wn_docker_net \ --ip 172.18.12.19 \ --sysctl net.core.somaxconn1024 \ -e TIME_ZONE"Asia/Shanghai" -e TZ"Asia/Shanghai"…

电磁兼容EMC理论基础汇总

目录 0. 序言 1. EMC的基础介绍 1.1 EMC电磁兼容的定义 1.2 EMC的重要性 1.3 EMC的三要素 2. 库仑定律 3. 趋肤效应与趋肤深度 4. 电阻抗公式 4.1 电阻 4.2 容抗 4.3 感抗 4.4 电路元件的非理想性 5. 麦克斯韦方程组 5.1 高斯磁定律 5.2 高斯定律 5.3 法拉…

【FPGA】Verilog:二进制并行加法器 | 超前进位 | 实现 4 位二进制并行加法器和减法器 | MSI/LSI 运算电路

Ⅰ. 前置知识 0x00 并行加法器和减法器 如果我们要对 4 位加法器和减法器进行关于二进制并行运算功能&#xff0c;可以通过将加法器和减法器以 N 个并行连接的方式&#xff0c;创建一个执行 N 位加法和减法运算的电路。 4 位二进制并行加法器 4 位二进制并行减法器 换…

YoloV8改进策略:Swift Parameter-free Attention,无参注意力机制,超分模型的完美迁移

摘要 https://arxiv.org/pdf/2311.12770.pdf https://github.com/hongyuanyu/SPAN SPAN是一种超分网络模型。SPAN模型通过使用参数自由的注意力机制来提高SISR的性能。这种注意力机制能够增强重要信息并减少冗余,从而在图像超分辨率过程中提高图像质量。 具体来说,SPAN模…

J-Link RTT的使用(原理 + 教程 + 应用 + 代码)

MCU:STM32F407VE MDK:5.29 IAR:8.32 目录--点击可快速直达 目录 写在前面什么是RTT?RTT的工作原理RTT的性能快速使用教程高级使用教程附上测试代码2019年12月27日更新--增加打印float的功能 写在前面 本文介绍了J-Link RTT的部分使用内容&#xff0c;很多地方参考和使用…

ImportError: cannot import name ‘metadata‘ from ‘importlib‘

yolov8 编译问题 ImportError: cannot import name ‘metadata’ from ‘importlib’ 将 from importlib import metadata 更改为 import importlib_metadata as metadata

canvas绘制单个圆和同心圆

代码实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdev…

【Java 基础】18 I/O流

文章目录 1.基本概念2.字节流3.字符流4.标准输入输出5.最佳实践 I/O流&#xff08;Input/Output 流&#xff09;是计算机程序中不可或缺的一部分&#xff0c; 往大了说所有的操作都是IO。Java 提供了强大而灵活的 I/O 框架&#xff0c;支持各种数据的 读取和 写入操作。 1.基…

网络安全--网络环境构成,系统的安全

2. 网络攻防环境 目标 了解攻防环境构成了解入侵检测系统&#xff08;平台&#xff09;的部署位置 2.1. 环境构成 2.1.1. 环境框图 一个基本的网络攻防实验环境包括&#xff1a;靶机、攻击机、入侵检测分析系统、网络连接四部分组成。 一个基础的网络攻防实验环境需要如下…

Mybatis 操作续集(结合上文)

当我们增加一个数据之后,如果我们想要获取它的 Id 进行别的操作,我们该如何获取 Id 呢? 用那个Options package com.example.mybatisdemo.mapper;import com.example.mybatisdemo.model.UserInfo; import org.apache.ibatis.annotations.*;import java.util.List;Mapper pub…

Leetcode刷题详解——乘积为正数的最长子数组长度

1. 题目链接&#xff1a;1567. 乘积为正数的最长子数组长度 2. 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你求出乘积为正数的最长子数组的长度。 一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。 请你返回乘积为正数的最长子数组长度。 示…

java面向对象 + 内存解析

这篇博客主要是重点讲解一些内存和一些规定的解释&#xff0c;对于定义我不会过多赘述&#xff0c;没有Java基础的话可以去翻看我之前的博客&#xff0c;学习完成之后再进行阅读。 面向对象可以说是Java中最重要的一部分了&#xff0c;这次复习我发现有几个点比较重要&#xf…

【Rust日报】2023-12-02 深度学习框架 Burn 发布 v0.11.0

深度学习框架 Burn 发布 v0.11.0 深度学习框架 Burn 发布 v0.11.0&#xff0c;新版本引入了自动内核融合&#xff08;Kernel Fusion&#xff09;功能&#xff0c;大大提升了访存密集型&#xff08;memory-bound&#xff09;操作的性能。同时宣布成立 Tracel AI (https://tracel…

深入理解 Kafka 集群搭建与管理

Apache Kafka 作为分布式流处理平台的核心&#xff0c;其集群搭建与管理是确保高可用性和高性能的关键。本文将深入研究 Kafka 集群的构建、配置、工作原理、节点角色以及一些高级管理策略&#xff0c;以助力读者更深层次地理解和灵活运用 Kafka 集群。 Kafka 集群基础 1 集群…

PHP开源问答网站平台源码系统 源码全部开源可二次开发 附带完整的搭建教程

目前&#xff0c;问答网站已经成为人们获取知识、交流思想的重要平台。然而&#xff0c;对于许多开发者来说&#xff0c;从头开始构建一个问答网站可能会面临各种挑战。今天&#xff0c;小编给大家介绍一款基于PHP的开源问答网站平台源码系统&#xff0c;它不仅源码全部开源&am…

HR看好的字符函数和字符串处理函数!!!

本篇会加入个人的所谓‘鱼式疯言’❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言,而是理解过并总结出来通俗易懂的大白话,我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的&#xff0c;可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 前言 在本篇…

基于maobox-gl 纯前端绘制全球色斑图

基于maobox-gl.js、turf.js 绘制全球色斑图绘制 1、准备全球的某一类的点位数据&#xff0c;可以使用turf.js 随机生成点&#xff0c;并点数据赋properties属性 let points turf.randomPoint(30, { bbox: [-180, -90, 180, 90]}); let interpolateOptions {gridType: "…

如何在线给官网搭建一个帮助文档?

在数字化时代&#xff0c;帮助文档已成为官网不可或缺的一部分。然而&#xff0c;传统的帮助文档往往只是简单地罗列问题和答案&#xff0c;缺乏互动性和用户体验。那么&#xff0c;如何在线给官网搭建一个富有创意且用户友好的帮助文档呢&#xff1f; | 一、打造沉浸式体验 传…

Google Chrome访问出现 NET::ERR_CERT_INVALID

Google Chrome访问出现 NET::ERR_CERT_INVALID然后访问不了当前网站&#xff0c;这个是由于证书失效了&#xff0c;临时解决方式是&#xff1a; 第一种方案&#xff1a; 在Chrome提示“您的连接不是私密连接”页面的空白区域点击一下&#xff0c;然后输入“thisisunsafe”(页…

逻辑漏洞测试靶场实验

任务一&#xff1a; 突破功能限制漏洞&#xff0c;要求突破查询按钮disabled限制&#xff0c;获取编号&#xff1a;110010的查询内容&#xff08;弹框中的flag&#xff09; 任务二&#xff1a;用户信息泄露漏洞&#xff0c;通过回显信息&#xff0c;以暴力破解法方式猜测系统中…