python调用动态链接库详解

  • Python 调用动态链接库
    • 环境说明
    • 构建动态链接库
    • python动态链接库基础调用
    • python动态链接库结构体调用
    • python动态链接库回调函数

本文介绍在linux环境下python调用c语言编写的动态链接库so。

Python 调用动态链接库

  • linux操作系统中动态链接库为so文件。
  • python调用so文件使用动态方式加载,python中使用ctypes库
  • ctypes是Python调用c的动态链接库的一个内置模块。

环境说明

  • 操作系统:linux
  • python: python3

构建动态链接库

  • 项目结构
├── CMakeLists.txt   # cmake构建配置文件
├── hello.cc            # 动态链接库源文件
└── hello.h         # 动态链接库头文件
  • CMakeLists.txt
cmake_minimum_required(VERSION 3.1)      # 设置cmake最小版本
project(hello)                  # 设置项目名称
set(src_h hello.h)              # 设置头文件
set(src_c hello.c)              # 设置源文件
add_library( hello SHARED ${src_h} ${src_c})    # 生成libhello.so库文件。
  • hello.h
#ifdef __cplusplus
extern "C"{#endif#ifndef _HELLO_H_
#define _HELLO_H_// -------------- so基础调用 -------------
void say_hello();               // 基础调用,无参数调用
void say_hello2(int iNum);          // 传递int类型参数
void say_hello3(const char *str);       // 传递char * 字符串
int  say_hello4(int iNum1,int Num2);        // 传递两个参数,并且带返回值。// -------------- so结构体调用 -------------
struct POINT{int x;int y;
};
struct POINT get_mouse_position();      // 返回结构体
struct POINT *get_position();           // 返回结构体指针
void release_point(struct POINT * ptrData); // 将结构指针作为参数// -------------- so 回调函数 -------------
typedef void (callback)();
typedef int (callback2)(int);
void send_message(int a, callback funcPtr); // 无参数的回调函数
int send_message2(int a, callback2 funcPtr);    // 带参数,带返回值的回调函数#ifdef __cplusplus
}
#endif
#endif
  • hello.c
#include <stdio.h>
#include <stdlib.h>
#include "hello.h"
void say_hello(){printf("hello\r\n");
}void say_hello2(int iNum){printf("hello2 num:%d\r\n",iNum);
}void say_hello3(const char *str){printf("hello3 str:%s\r\n",str);
}int  say_hello4(int iNum1,int iNum2){int res = iNum1 + iNum2;printf("hello4 res:%d\r\n",res);return res;
}
struct POINT get_mouse_position(){struct POINT temp;temp.x = 12;temp.y = 13;return temp;
}
struct POINT *get_position(){struct  POINT *temp =NULL;temp = (struct POINT *)malloc(sizeof(struct POINT));temp->x = 10;temp->y = 20;return temp;
}void release_point(struct POINT * ptrData){if(NULL != ptrData){free(ptrData);ptrData = NULL;   }
}
void send_message(int a, callback  funcPtr){printf("send_message a:%d\r\n",a);if(funcPtr != NULL)funcPtr();
}int send_message2(int a, callback2 funcPtr){printf("send_message2 a:%d\r\n",a);if(funcPtr != NULL){int res= funcPtr(6);printf("回调函数的执行结果为:%d\r\n",res);}return 5;
}
  • 构建步骤,如果生成libhello.so文件那么就构建成功了
mkdir build
cd build
cmake ..
make

python动态链接库基础调用

将so文件拷贝到py文件的同级目录
运行命令:

python3 main.py

目录结构如下:

├── libhello.so
└── main.py

main.py

import ctypes
from ctypes import *
solib =  ctypes.CDLL('./libhello.so')func_say_hello = solib.say_hello
func_say_hello()
print("func_say_hello 执行完毕!")
print("============================")func_say_hello2 = solib.say_hello2
func_say_hello2(2)
print("func_say_hello2 执行完毕!")
print("============================")func_say_hello3 = solib.say_hello3
str = "I love you"
func_say_hello3(str.encode("UTF-8"))
print("func_say_hello3 执行完毕!")
print("============================")func_say_hello4 = solib.say_hello4
res = func_say_hello4(5,6)
print("func_say_hello3 执行完毕!结果为:",res)
print("============================")

执行结果如下:

hello
func_say_hello 执行完毕!
============================
hello2 2
func_say_hello2 执行完毕!
============================
hello3 I love you
func_say_hello3 执行完毕!
============================
hello4 11
func_say_hello3 执行完毕!结果为: 11
============================

python动态链接库结构体调用

main.py

import ctypes
from ctypes import *class PyPointStruct(Structure):_fields_ = [("x", c_int),("y", c_int),]solib =  ctypes.CDLL('./libhello.so')func_get_mouse_position = solib.get_mouse_position
func_get_mouse_position.restype = PyPointStruct # 设置函数返回结果的类型为结构体
resp = func_get_mouse_position()
print("res2:",resp.x)
print("res2:",resp.y)
print("============================")func_get_position = solib.get_position
func_get_position.restype = POINTER(PyPointStruct) # 设置函数返回结果的类型为结构体指针
resb = func_get_position()
print("res3:",resb.contents.x)
print("res3:",resb.contents.y)
print("============================")

执行结果如下:

res2: 12
res2: 13
============================
res3: 10
res3: 20
============================

python动态链接库回调函数

main.py

import ctypes
from ctypes import *solib =  ctypes.CDLL('./libhello.so')    # 加载动态链接库def cb_sayhello():                     # 无参数的回调函数print("python hello")def cb_sayhello2(res):                 # 带参数有返回值的回调函数。print("python hello2,res:",res)return 1024solib =  ctypes.CDLL('./libhello.so')   func_send_message = solib.send_message
# CFUNCTYPE定义方法的签名,第一参数表示方法的返回类型,后面开始编译参数的类型
funcStruct =  CFUNCTYPE(None)
solib.send_message(10,funcStruct(cb_sayhello))
print("============================")send_message2 = solib.send_message2
# CFUNCTYPE定义方法的签名,第一参数表示方法的返回值,后面开始编译参数的类型
funcStruct2 =  CFUNCTYPE(c_int,c_int)
send_message2(10,funcStruct2(cb_sayhello2))
print("============================")

执行结果:

send_message a:10
python hello
============================
send_message2 a:10
python hello2,res: 6
回调函数的执行结果为:1024
============================

Note:在一个项目中,我使用python调用动态库,发现奔溃的现象。
具体问题如下,
我将python中的回调函数传递给so调用,但是so的程序中使用了多线程调用回调函数,由于python的回调函数时通过构造对象的方式调的send_message2(10,funcStruct2(cb_sayhello2)) 其中,funcStruct2(cb_sayhello2)是一个对象,因此在这个函数执行完成后会释放这个对象,在so的程序中多线程函数执行回调函数对象就已经被释放了 ,因此照成回调函数调用崩溃的情况。

代码下载地址
https://download.csdn.net/download/arv002/33253778

python调用C语言动态链接库详解相关推荐

  1. python调用C语言ctypes详解

    ctypes是Python的一个外部库,提供和C语言兼容的数据类型,可以很方便地调用DLL中输出的C接口函数. 1.加载dll和取出函数 from ctypes import * dll = cdll ...

  2. Python的C语言接口 - 详解官方文档

    Python的C语言接口 - 详解官方文档 索引 Python的C语言接口 - 详解官方文档 介绍 / Introduce 代码标准 / Coding Standards 包含文件 / Include ...

  3. 百度翻译API限量后,python调用有道翻译详解

    背景 8月1日,百度翻译API宣布"调整" 刚开始,以为是调用百度API代码出问题了,一直报错 后查,免费还有,但是从旧时不限量 改为5万字符/月,原来是"羊毛被薅光了& ...

  4. python预处理c语言_详解C语言编程中预处理器的用法

    预处理最大的标志便是大写,虽然这不是标准,但请你在使用的时候大写,为了自己,也为了后人. 预处理器在一般看来,用得最多的还是宏,这里总结一下预处理器的用法. #include #define MACR ...

  5. python调用c语言内核计算,在Linux上实现Python调用C语言函数

    一般思路 Python中内置ctypes库,需调用c编译成的.so文件来实现函数调用. 假设我们所需调用的c文件名为test.c,文件里有我们需要的函数func(x,y). 将.c文件编译成 .so文 ...

  6. python语言入门详解-python初级教程:入门详解

    python初级教程:入门详解 Crifan Li 目录 前言 .................................................................... ...

  7. 代码检查规则:Python语言案例详解

    在之前的文章中代码检查规则:Java语言案例详解学习了Java的检查规则.我们今天将学习<代码检查规则:Python语言案例详解>,内容主要分为两个部分:Python的代码检查规则和Pyt ...

  8. python语言编程基础-Python语言入门详解!快速学成Python!

    原标题:Python语言入门详解!快速学成Python! 很多技能是被职场所需要的,但很可惜... 这些技能在大学中并学习不到. 大学和职场现实存在的横沟对大部分同学来说难以跨越或碰得头破血流... ...

  9. python语言入门m-Python语言入门详解!快速学成Python!

    今日主题 "Python语言入门详解" 近两年来,Python语言借着数据科学和人工智能的"东风"成为了最流行的编程语言--街头巷尾人们口口相传.同时,Pyth ...

最新文章

  1. 根据值 加密后的值 算出key_Bugku:加密 rsa
  2. 安装Scrapy时:Microsoft Visual C++ 9.0 is required
  3. 【朋克智库】比特币详解2.0——比特币的沉沦
  4. vi编辑器基本使用方法
  5. TCL座机日期时间调整
  6. Kafka的存储设计
  7. 数据分析与挖掘建模实战002:数据获取
  8. blasphemy - 题解
  9. 禅道、码云、coding、redmine、jira、teambition几大敏捷开发项目管理系统试用对比体验
  10. Centos7端口查看命令
  11. indesign安装包.exe 自动简繁互转for_adobe Indesign (ID)插件集打包下载
  12. 用js转换joson返回数据库的时间格式为/Date(*************)/
  13. QFN封装芯片手工焊接方法
  14. Linux下的mplayer播放器移植与使用
  15. Wyn Enterprise 报表数据过滤
  16. 关于无盘产品市场调查
  17. TensorRT debug及FP16浮点数溢出问题分析
  18. 使用诚龙网维PXE网克工具需注意的几点 不断更新中
  19. 20145226夏艺华 《Java程序设计》实验报告二
  20. word退格键不管用

热门文章

  1. 高端运动耳机哪个品牌最好用、最新款运动耳机推荐
  2. 数组 去除重复元素 的三种方法
  3. openflow阅读感悟
  4. vue制定文章内容模板,文章的每一段对应数组的每一项,支持存放多张图片
  5. redis详细介绍附实例代码--看一篇就够了
  6. 【180629】VC++滚彩球游戏附源程序
  7. 007-2018-09-11 基础数据类型的补充
  8. python可变参数的定义_Python函数可变参数
  9. 用python分析HTTP请求中各过程用时情况(通过分析抓包文件pcap实现)
  10. net-java-php-python-个人财物管理系统计算机毕业设计程序个人财物管理系统计算机毕业设计程序