• 技术文章 >Python技术 >Python基础教程

    python怎么生成dll

    爱喝马黛茶的安东尼爱喝马黛茶的安东尼2019-09-21 10:14:09原创13972

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

    如今,随着深度学习的发展,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。

    相关推荐:《Python教程

    接下来,我们执行如下命令,把这个代码变成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>
    }
     
    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一起发布即可。

    专题推荐:python 生成 dll
    上一篇:linux如何编写python脚本 下一篇:python如何导入csv文件格式

    相关文章推荐

    • python27.dll 是什么• python20.dll是什么

    全部评论我要评论

    © 2021 Python学习网 苏ICP备2021003149号-1

  • 取消发布评论
  • 

    Python学习网