Python調(diào)用C++函數(shù)(SWIG瓷马,VS2013使用numpy.i完成Numpy與C++數(shù)組轉(zhuǎn)換)

最近嘗試使用Python調(diào)用C++函數(shù)拴还,發(fā)現(xiàn)網(wǎng)上都是一些簡(jiǎn)單的例子,涉及到Python Numpy數(shù)組與C++數(shù)組轉(zhuǎn)換的例子比較少欧聘,所以花費(fèi)了一些時(shí)間片林,搞懂了SWIG使用numpy.i接口文件完成Numpy與C++數(shù)組轉(zhuǎn)換。相比于其它幾種方式,使用SWIG接口文件編寫(xiě)比較簡(jiǎn)單费封,編譯也很方便焕妙,主要是不太好調(diào)試,因?yàn)槭蔷幾g成.dll或者.so才能在Python中調(diào)用弓摘。
1.安裝SWIG
windows:官網(wǎng)下載焚鹊,解壓到D盤,將swig.exe所在文件夾添加到系統(tǒng)路徑韧献,如:D:\swigwin-3.0.12
Linux:sudo apt-get install swig
2.下載numpy.i文件
有些在numpy安裝目錄下直接就有末患,沒(méi)有的話可以到GitHub下載numpy.i地址numpy.i說(shuō)明文檔势决,numpy/tools/swig/numpy.i
3.編寫(xiě)自己的函數(shù)接口文件

//cos_doubles.h
void cos_doubles(double*in_array,double*out_array,intsize);

//cos_doubles.cpp
#include <math.h>

/*  Compute the cosine of each element in in_array, storing the result in
 *  out_array. */
void cos_doubles(double * in_array, double * out_array, int size){
    int i;
    for(i=0;i<size;i++){
        out_array[i] = cos(in_array[i]);
    }
}

根據(jù)numpy.i說(shuō)明文檔撰寫(xiě)cos_doubles.i文件:

/*  Example of wrapping a C function that takes a C double array as input using
 *  numpy typemaps for SWIG. */

%module cos_doubles
%{
    /* the resulting C file should be built as a python extension */
    #define SWIG_FILE_WITH_INIT
    /*  Includes the header in the wrapper code */
    #include "cos_doubles.h"
%}

/*  include the numpy typemaps */
%include "numpy.i"
/*  need this for correct module initialization */
%init %{
    import_array();
%}

/*  typemaps for the two arrays, the second will be modified in-place */
%apply (double* IN_ARRAY1, int DIM1) {(double * a, int size_a)}
%apply (double* INPLACE_ARRAY1, int DIM1) {(double *b, int size_b)}

/*  Wrapper for cos_doubles that massages the types */
%inline %{
    /*  takes as input two numpy arrays */
    void cos_doubles_func(double * a, int size_a, double* b, int size_b) {
        /*  calls the original funcion, providing only the size of the first */
        cos_doubles(a, b, size_a);
    }
%}

如果是固定大小的數(shù)組阻塑,也可以使用%apply (double IN_ARRAY1[ANY]) {(double a[63])}方式
4.使用SWIG編譯生成.py和.cxx
將numpy.i、cos_doubles.h果复、cos_doubles.cpp陈莽、cos_doubles.i放在同一文件夾下,命令行輸入(Linux與windows相同虽抄,C語(yǔ)言去掉-c++):

swig -c++ -python cos_doubles.i

此時(shí)文件夾下會(huì)生成cos_doubles.py與cos_doubles_wrap.cxx文件
5.1.編譯生成動(dòng)態(tài)鏈接庫(kù)文件(Linux)
Linux:新建setup.py文件

from distutils.core import setup, Extension
import numpy


cos_doubles_module = Extension('_cos_doubles',
                           sources=['cos_doubles_wrap.cxx', 'cos_doubles.cpp'], )

setup (name = 'cos_doubles',
       version = '0.1',
       author      = "SWIG Docs",
       description = """Simple swig example from docs""",
       ext_modules = [cos_doubles_module],
       include_dirs = [numpy.get_include()],
       py_modules = ["cos_doubles"], )

命令行輸入:

python setup.py build_ext --inplace

此時(shí)文件夾下會(huì)生成_cos_doubles.so文件走搁,新建runme.py演示程序,測(cè)試能否調(diào)用:

import numpy as np
import matplotlib.pyplot as plt
import cos_doubles

x = np.arange(0, 2 * np.pi, 0.1)
y = np.empty_like(x)

cos_doubles.cos_doubles_func(x, y)
plt.plot(x, y)
plt.show()

5.2.編譯生成動(dòng)態(tài)鏈接庫(kù)文件(Windows)
Windows下也可以嘗試Linux下相同的方法迈窟,但是可能會(huì)報(bào)錯(cuò)私植,我反正沒(méi)有成功,下面使用VS2013生成動(dòng)態(tài)鏈接庫(kù)车酣。
1.新建一個(gè)Win32 Console Application工程 => 在向?qū)е悬c(diǎn)next => Application type選擇DLL,在Additional options中選擇Empty project
2.向Header Files中加入cos_doubles.h,向Source File中加入cos_doubles.cpp和cos_doubles_wrap.cxx,向工程中加入numpy.i和cos_doubles.i (這是可能會(huì)彈出一個(gè)對(duì)話框曲稼,我選的是'否')

工程文件結(jié)構(gòu)
3.project>Properties中點(diǎn)Configuration Manager,設(shè)置Configration為Release,Platform為×64 => Configuration Properties>VC++ Directories中湖员,在show directories for 'Include files'中加入Python include 目錄'D:\Anaconda3\include' numpy include目錄:'D:\Anaconda3\Lib\site-packages\numpy\core\include'贫悄,show dirctories for 'Library files'中加入Python lib目錄'D:\Anaconda3\libs',C/C++>Preprocessor>Preprocessor Definition 加入

WIN32
_DEBUG
_CONSULE
_CRT_SECURE_NO_WARNINGS
屬性配置

右鍵工程娘摔,點(diǎn)擊Build窄坦,運(yùn)氣好的話可能一次成功,跳到最后一步凳寺,如果報(bào)找不到python35_d.lib鸭津,則需要修改Python\include 目錄下的 pyconfig.h, object.h 兩個(gè)文件

a. 修改 pyconfig.h 
修改 
#ifdef _DEBUG 
# define Py_DEBUG 
#endif 
為 
#ifdef _DEBUG 
//# define Py_DEBUG 
#endif 

修改 
# ifdef _DEBUG 
# pragma comment(lib,"python24_d.lib") 
# else 
# pragma comment(lib,"python24.lib") 
# endif /* _DEBUG */ 
為 
# ifdef _DEBUG 
# pragma comment(lib,"python24.lib") 
# else 
# pragma comment(lib,"python24.lib") 
# endif /* _DEBUG */ 

b. 修改object.h 
修改 
#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) 
#define Py_TRACE_REFS 
#endif 
為 
#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) 
// #define Py_TRACE_REFS 
#endif

最后Build Solution,在Release文件夾中會(huì)生成cos_doubles.dll,把它改名成_cos_doubles.pyd肠缨。把cos_doubles.py, _cos_doubles.pyd和測(cè)試文件放到同一個(gè)文件夾中,python運(yùn)行測(cè)試逆趋。
最終結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晒奕,隨后出現(xiàn)的幾起案子父泳,更是在濱河造成了極大的恐慌般哼,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惠窄,死亡現(xiàn)場(chǎng)離奇詭異蒸眠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)杆融,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門楞卡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人脾歇,你說(shuō)我怎么就攤上這事蒋腮。” “怎么了藕各?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵池摧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我激况,道長(zhǎng)作彤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任乌逐,我火速辦了婚禮竭讳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浙踢。我一直安慰自己绢慢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布洛波。 她就那樣靜靜地躺著胰舆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蹬挤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天闻伶,我揣著相機(jī)與錄音,去河邊找鬼够话。 笑死欣尼,一個(gè)胖子當(dāng)著我的面吹牛停蕉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钙态,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼慧起,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了册倒?” 一聲冷哼從身側(cè)響起蚓挤,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驻子,沒(méi)想到半個(gè)月后灿意,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡崇呵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年缤剧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片域慷。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荒辕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芒粹,到底是詐尸還是另有隱情兄纺,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布化漆,位于F島的核電站估脆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏座云。R本人自食惡果不足惜疙赠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朦拖。 院中可真熱鬧圃阳,春花似錦、人聲如沸璧帝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)睬隶。三九已至锣夹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苏潜,已是汗流浹背银萍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恤左,地道東北人贴唇。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓搀绣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親戳气。 傳聞我的和親對(duì)象是個(gè)殘疾皇子链患,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容