使用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一塊兒發佈便可。
相關文章
相關標籤/搜索