使用python创建生成动态链接库dll的方法


Posted in Python onMay 09, 2020

如今,随着深度学习的发展,python已经成为了深度学习研究中第一语言。绝大部分的深度学习工具包都有python的版本,很多重要算法都有python版本的实现。为了将这些算法应用到具体工程中,这些工具包也提供了不同类型的接口。

动态链接库(.dll,.so)是系统开发中一种非常重要的跨语言协作方式。把python语言写成的算法编译成动态库,能够提供给其他语言调用,这能够在很大程度上提高算法的开发效率。

但是,虽然python可以调用其他语言生成的动态库,python作为一种脚本语言,本身是不能直接编译生成动态库的。为了生成动态库,我们借助cython,将python脚本变成c语言文件。具体过程,我们通过一个简单的例子来解释。

def str_add(str1,str2): 
    return int(str1) + int(str2)

这个代码,将两个数字组成的字符串转化成数字,并求和。我们把这个代码保存成run.py备用。根据cython的语法,我们给出cython版本的函数:

cdef public str_add(str1,str2):
     return int(str1) + int(str2)

和前面python版本的相比,cdef替换了def,并加了public关键字,表示这个函数要导出。将这个代码保存成pyx文件,比如run.pyx。

接下来,我们执行如下命令,把这个代码变成c语言版本:

cython run.pyx

这时,目录下面生出来run.h和run.c两个文件。这个两个文件通过调用python的C-API实现了run.py代码的功能。

接下来,我们编写动态库的主文件dllmain.c:

#include <Python.h>
#include <Windows.h>
#include "run.h"
 
extern __declspec(dllexport) int __stdcall _str_add(const char * a, const char * b) {
  return PyLong_AsLong(str_add(PyUnicode_FromString(a),PyUnicode_FromString(b)));<br data-filtered="filtered">
}
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved) {
  switch( fdwReason ) {
    case DLL_PROCESS_ATTACH:
      Py_Initialize();
      PyInit_run(); #dll初始化的时候调用,这是python3的写法,python2改成,initrun()。参见生成的run.h
      break;
    case DLL_PROCESS_DETACH:
      Py_Finalize();
      break;
  }
  return TRUE;
}

该文件定义了导出函数_str_add。在python中,所有数据都以pyobject进行存储。这个函数通过PyUnicode_FromString,将两个字符串变成python对象类型,并调用run.h里面的函数str_add求和,并把结果通过PyLong_AsLong函数从python对象,变成整形数字。

我们可以通过如下命令,将这个代码编译生成dll:

cl /LD dllmain.c run.c -IC:\python36\include C:\python36\libs\python36.lib

这里python的路径,根据不同电脑python的安装位置,做相应调整。

生成的dll,我们写个简单调用,测试一下:

#include "stdio.h"
#include "stdlib.h"
extern __declspec(dllexport) int __stdcall _str_add(const char * a, const char * b);
 
#pragma comment(lib,"dllmain.lib")
 
int main()
{
 printf("%d \n", _str_add("123","456"));
 return 0;
}

输出结果: 579,正好等于123+456。

通过以上步骤,我们已经能够把python代码实现的功能,封装成动态库。然而,这个动态库无法在没有安装python的机器上面运行。事实上,python代码,通常需要很多依赖包才能运行。而且,每段代码需要的依赖包是不一样的。为了查找这些包,我们采用另外一个工具pyinstaller。具体步骤简介如下:

virtualenv envpack # 创建新的环境,python包依赖比较复杂,创建新环境可以减少最终引入的包
cd envpack # 进入目录
#复制run.py到这个目录,run.py运行需要的包,和最终dll需要的包是一样的
Scripts\activate # 激活并切换到virtualenv环境
pip install pyinstaller # 安装打包工具pyinstaller
pip install numpy # 安装numpy等脚本需要的库,查看你的import
pyinstaller run.py # 打包命令
Scripts\deactivate # 打包成功后,使用命令取消激活环境
需要打包的文件在envpack\dist, 包括很多.dll和.pyd文件,把这些文件和dll一起发布即可。

总结

到此这篇关于使用python创建生成动态链接库dll的方法的文章就介绍到这了,更多相关python动态链接库dll内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python中正则表达式的使用详解
Oct 17 Python
python获取指定网页上所有超链接的方法
Apr 04 Python
基于wxpython开发的简单gui计算器实例
May 30 Python
python实现机器人行走效果
Jan 29 Python
pandas 数据索引与选取的实现方法
Jun 21 Python
Python在Matplotlib图中显示中文字体的操作方法
Jul 29 Python
PyQt5基本控件使用详解:单选按钮、复选框、下拉框
Aug 05 Python
python-web根据元素属性进行定位的方法
Dec 13 Python
使用TensorFlow直接获取处理MNIST数据方式
Feb 10 Python
python正则表达式的懒惰匹配和贪婪匹配说明
Jul 13 Python
python中numpy数组与list相互转换实例方法
Jan 29 Python
利用python实时刷新基金估值(摸鱼小工具)
Sep 15 Python
浅析python 动态库m.so.1.0错误问题
May 09 #Python
Python实现常见的几种加密算法(MD5,SHA-1,HMAC,DES/AES,RSA和ECC)
May 09 #Python
Python发送邮件封装实现过程详解
May 09 #Python
pycharm第三方库安装失败的问题及解决经验分享
May 09 #Python
pycharm无法安装第三方库的问题及解决方法以scrapy为例(图解)
May 09 #Python
pip安装提示Twisted错误问题(Python3.6.4安装Twisted错误)
May 09 #Python
Python接口测试数据库封装实现原理
May 09 #Python
You might like
php模板函数 正则实现代码
2012/10/15 PHP
ThinkPHP有变量的where条件分页实例
2014/11/03 PHP
支持png透明图片的php生成缩略图类分享
2015/02/08 PHP
Laravel 队列使用的实现
2019/01/08 PHP
laravel邮件发送的实现代码示例
2020/01/31 PHP
输入框的字数时时统计—关于 onpropertychange 和 oninput 使用
2011/10/21 Javascript
Jquery实现图片放大镜效果的思路及代码(自写)
2013/10/18 Javascript
浅析node连接数据库(express+mysql)
2015/11/30 Javascript
JavaScipt中栈的实现方法
2016/02/17 Javascript
基于JQuery的$.ajax方法进行异步请求导致页面闪烁的解决办法
2016/05/10 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
2017/07/13 Javascript
在Vue.js中使用Mixins的方法
2017/09/12 Javascript
详解基于vue-router的动态权限控制实现方案
2017/09/28 Javascript
js实现会跳动的日历效果(完整实例)
2017/10/18 Javascript
详解Immutable及 React 中实践
2018/03/01 Javascript
JS window对象简单操作完整示例
2020/01/14 Javascript
[44:40]Spirit vs Navi Supermajor小组赛 A组败者组第一轮 BO3 第一场 6.2
2018/06/03 DOTA
[35:29]Secret vs VG 2018国际邀请赛淘汰赛BO3 第三场 8.23
2018/08/24 DOTA
Python实现判断一个字符串是否包含子串的方法总结
2017/11/21 Python
python判断一个集合是否为另一个集合的子集方法
2018/05/04 Python
Flask框架配置与调试操作示例
2018/07/23 Python
Python面向对象之类和对象实例详解
2018/12/10 Python
Python2与Python3的区别实例分析
2019/04/11 Python
Pandas中两个dataframe的交集和差集的示例代码
2020/12/13 Python
Html5页面二次分享的实现
2018/07/30 HTML / CSS
美国网上眼镜商城:Zenni Optical
2016/11/20 全球购物
Bulk Powders意大利:运动补充在线商店
2019/02/09 全球购物
小学运动会广播稿200字(十二篇)
2014/01/14 职场文书
九年级数学教学反思
2014/02/02 职场文书
求职自荐信怎么写
2014/03/06 职场文书
公司委托书范本
2014/04/04 职场文书
家长通知书教师评语
2014/04/17 职场文书
税务干部群众路线教育实践活动对照检查材料
2014/09/20 职场文书
2014年司法局工作总结
2014/12/11 职场文书
事业单位工作人员2015年度思想工作总结
2015/10/15 职场文书
Python Django 后台管理之后台模型属性详解
2021/04/25 Python