首页 > 编程语言 >python使用ctypes调用gcc编译的dll之ctypes的使用

python使用ctypes调用gcc编译的dll之ctypes的使用

时间:2023-07-27 15:12:37浏览次数:50  
标签:gcc python double char print int ctypes res test

简介

ctypes 是 Python 的外部函数库。它提供了与 C 兼容的数据类型,并允许调用C或C++编译后的DLL 或共享库中的函数。可使用该模块以纯 Python 形式对这些库进行封装。
本例中代码基于window系统,python为64位3.9.12,如需在liunx上使用请参考上篇博客

1、代码的基础结构如下

1.1 新建header.h代码如下

#pragma once

#define DllExport __declspec( dllexport )
struct Point{
    int x;
    double y;
};


extern "C"
{
    DllExport void hello_world(void);
    DllExport char print_chr(char chr);
    DllExport double add(int num1, float num2, double num3);
    DllExport char* test_chrp(char *s);
    DllExport int test_intp(int arr1[], int arr1_len, int arr2[][2], int arr2_len);
    DllExport double* test_dabp(int *p1, float *p2, double *p3);
    DllExport void print_point(struct Point point);
}

1.2 新建test.c代码如下

#include <iostream>
#include <string.h>
//#include <stdio.h>
#include "header.h"

//void hello_world() {
//    printf("hello world");
//}

void hello_world() {
    std::cout << "hello world" << std::endl;
}

char print_chr(char chr){
   std::cout << chr << std::endl;
   return chr;
}

double add(int num1, float num2, double num3){
    return num1 + num2 + num3;
}

char* test_chrp(char *s) {
    static char hel[] = "hello";
    char *p;
    int i;
    p = hel;
    for (i = 0; i < 2; i++)
    {
        *(s + i) = hel[i];
    }
    return p;
}


double* test_dabp(int *p1, float *p2, double *p3){
    // C 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量
    static double da[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
    double *p;
    int i;
    da[0] = da[0] + *p1 + *p2 + *p3;
    p = da;
    return p;
}

int test_intp(int arr1[], int arr1_len, int arr2[][2], int arr2_len){
    int i;

    for ( i = 0; i < arr1_len; i++ )
    {
        arr1[i] = arr1[i] + 10;
//        std::cout << "arr1[" << i << "]: ";
//        std::cout << arr1[i]<< std::endl;
    }

    int k, j;
    for ( int k = 0; k < arr2_len; k++ ){
      for ( int j = 0; j < 2; j++ )
      {
         arr2[k][j] = arr2[k][j] + 100;
//         std::cout << "arr2[" << k << "][" << j << "]: ";
//         std::cout << arr2[k][j]<< std::endl;
      }
     }

    return 0;
}


void print_point(struct Point point){
    std::cout << "x: "<< point.x << ", y: "<< point.y << std::endl;
}


1.3 编译C++代码

g++ test.cpp -fPIC -static -shared -o test.dll

1.4 新建test.py代码如下

# -*- coding: UTF-8 -*-
# import ctypes
from ctypes import *

# test =  cdll.LoadLibrary('./test.dll')
test = CDLL('./test.dll')

test.hello_world()

# C/C++常用的基本数据类型作为函数的参数的使用
# 以char类型作为参数和返回值
test.print_chr.restype = c_char
chr_res = test.print_chr(c_char(b'Y'))
print("chr_res: ", chr_res)

# 以int, float, double类型作为参数并返相加后的double类型结果
test.add.restype = c_double
test.add.argtypes = [c_int,  c_float,  c_double]
int_res = test.add(c_int(5),  c_float(0.5),  c_double(0.05))
print("double_res: ", int_res)

# 以char指针作为参数,并返回一个char指针
test.test_chrp.restype = c_char_p
test.test_chrp.argtypes = [c_char_p]
# cp = cast((c_char * 2)(), c_char_p)
cp = c_char_p(b"s")
res = test.test_chrp(cp)
print(res)
print(cp.value)

# 以int, float, double类型的指针作为参数并返相加后的double的指针类型结果
test.test_dabp.restype = POINTER(c_double)
test.test_dabp.argtypes = [POINTER(c_int), POINTER(c_float), POINTER(c_double)]
res = test.test_dabp(pointer(c_int(100)), pointer(c_float(0.1)), pointer(c_double(0.01)))
# print(res)
# print(res[1])
for i in range(5):
    print(res[i])

# 用int类型的一维数组和二维数组作为函数参数, 然后将arr1的每个元素加10, arr2的每个元素加100,并打印数组元素的值
# 第一种方式使用数组作为传参的参数
test.test_intp.argtypes = [c_int * 5, c_int, (c_int * 2)*5, c_int]
arr1 = (c_int * 5)(1, 2, 3, 4, 5)
arr2 = ((c_int * 2)*5)((1, 2), (3, 4), (5, 6), (7, 8), (9, 10))
res = test.test_intp(arr1, 5, arr2, 5)

for i in range(5):
    print("python arr1:", arr1[i])

for i in range(5):
    for j in range(2):
        print("python arr2:", arr2[i][j])

# 第二种方式使用指针作为传参的参数
test.test_intp.argtypes = [POINTER(c_int), c_int, POINTER(c_int), c_int]
arr1 = (c_int * 5)(1, 2, 3, 4, 5)
arr1 = cast(arr1, POINTER(c_int))
arr2 = ((c_int * 2)*5)((1, 2), (3, 4), (5, 6), (7, 8), (9, 10))
arr2 = cast(arr2, POINTER(c_int))
res = test.test_intp(arr1, 5, arr2, 5)

for i in range(5):
    print("python arr1:", arr1[i])

for i in range(10):
    print("python arr2:", arr2[i])


# 使用c语言中的结构体
class Point(Structure):

    _fields_ = (
        ('x', c_int),
        ('y', c_double),
    )


point = Point(1, 2)
print(point.x, point.y)

test.print_point(point)
print(point.x, point.y)

1.5 运行python代码

python test.py

标签:gcc,python,double,char,print,int,ctypes,res,test
From: https://www.cnblogs.com/chen55555/p/17580463.html

相关文章

  • Python数据可视化-折线图
    Python数据可视化-折线图一、JSON数据格式1.1什么是jsonJSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据JSON本质上是一个带有特定格式的字符串主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互1.2json......
  • python 日志
    #coding:utf-8importloggingimportsysimportosimportdatetimefromloggingimporthandlersclassLogger(object):def__init__(self,name):LOGGING_TO_CONSOLE=TrueLOGGING_LEVEL=logging.DEBUGLOGGING_FORMATTER='%(asc......
  • python使用多进程multiprocessing执行报错
        inthemainmodule:      if__name__=='__main__':        freeze_support()        ...    The"freeze_support()"linecanbeomittediftheprogram    isnotgoingtobefrozentop......
  • 一个能提高写代码效率的方法:AI+Python
    ​ 在今年之前,我们都以为AI只能取代底层的劳动密集型工作,涉及创意、思维和感情的工作是不会被AI取代的,但自今年年初,人工智能异军突起狠狠将我们打脸。 今年火爆的聊天机器人仅仅作为“弱人工智能”,就让大批翻译、文案、设计、程序员等行业人员瑟瑟发抖,各路专家认为,未来人工......
  • 轻松用Python控制你的手机
    ​“Python编程几乎能做任何事,只要你敢想,敢尝试!”,今天来看下用Python代码怎么来控制你的安卓手机。具体的说是代替你的手,实现自动的触摸和一些动作,实现自动化操作! 主要用的是安卓手机的Android调试桥(AndroidDebugBridge),它是一个非常有用的工具!本文的这个快速指南中,我将向你......
  • 基于Python的HTTP代理爬虫开发初探
     在数字化时代,网络数据的获取对于企业和个人都变得至关重要。然而,许多网站为了保护其数据和资源,采取了反爬虫措施,使得我们无法直接访问和获取所需的信息。这时,HTTP代理爬虫就成为了一项强大的工具,它可以帮助我们绕过限制,有效地进行数据采集。在本文中,将介绍基于Python的HTTP代理......
  • [oeasy]python0075_删除变量_del_delete_variable
    删除变量回忆上次内容上次我们研究了字节序字节序有两种 符号英文名称中文名称<little-endian小字节序>big-endian大字节序字节序用来明确整型数字存储的顺序 如果读写数字出了错......
  • 深入Scikit-learn:掌握Python最强大的机器学习库
    本篇博客详细介绍了Python机器学习库Scikit-learn的使用方法和主要特性。内容涵盖了如何安装和配置Scikit-learn,Scikit-learn的主要特性,如何进行数据预处理,如何使用监督学习和无监督学习算法,以及如何评估模型和进行参数调优。本文旨在帮助读者深入理解Scikit-learn,并有效地应用在......
  • 使用Python统计下桌面某个文件夹下(含多层子文件夹)具体文件的数量(方法二)
    大家好,我是皮皮。一、前言前几天在Python最强王者群【东哥】问了一个Python自动化办公的问题,一起来看看吧。这个是他自己在实际工作中遇到的需求,正好遇到了这个问题,想着用Python来实现下。二、实现过程上一篇文章中已经分享了一个方法,这一篇文章继续分享另外一个方法,由【小王......
  • python设计模式运用
    工厂+策略+注册classVideoFactory(object):def__init__(self):self.video={}defregister_video(self,name,video):self.video[name]=videodefcreate_video(self,name):ifnameinself.video:returnself.v......