使用python建立生成动态连接库dll

现在,随着深度学习的发展,python已经成为了深度学习研究中第一语言。绝大部分的深度学习工具包都有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.pyxcode

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

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

#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)));
} 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。具体步骤简介以下:

  1. virtualenv envpack # 建立新的环境,python包依赖比较复杂,建立新环境能够减小最终引入的包
  2. cd envpack # 进入目录
  3. #复制run.py到这个目录,run.py运行须要的包,和最终dll须要的包是同样的
  4. Scripts\activate # 激活并切换到virtualenv环境
  5. pip install pyinstaller # 安装打包工具pyinstaller
  6. pip install numpy # 安装numpy等脚本须要的库,查看你的import
  7. pyinstaller run.py # 打包命令
  8. Scripts\deactivate # 打包成功后,使用命令取消激活环境
  9. 须要打包的文件在envpack\dist, 包括不少.dll和.pyd文件,把这些文件和dll一块儿发布便可。
相关文章
相关标签/搜索