① 如何編譯c文件中調用 cython
以下總結出幾種在python 中調用 C/C++ 代碼的方法
--------------------------------------------------------------------
發現做便捷的是使用popen
from os import popen
popen('/home/pengyan/Downloads/VIC/sanxia/vicNl -g /home/pengyan/Downloads/VIC/sanxia/xings_global')
popen('/home/pengyan/Downloads/VIC/sanxia/rout /home/pengyan/Downloads/VIC/sanxia/xings_rout')
?? 目前還不會用python 切換文件目錄
可以採用絕對路徑,但是好像絕對路徑時,計算速度變慢
-------------------------------------------------------------------
使用ctypes 模塊調用 C 動態庫
從Python2.5 開始, Python 開始提供 ctypes 模塊來提供對 C 語言編譯的動態庫文件的調用。注意, 這里特指C 的動態庫 ,用C++ 編譯的動態庫 ctypes 雖然能夠載入,但調用時的函數名已經由於 C++ 的重載特性被加以修改,難以調用。 使用 ctypes 調用 C 動態庫的好處在於不用進行額外的開發,可以直接使用編譯好的動態庫。 ctypes 提供了完整的 C 類型封裝,也支持自定義類型,大大減少在調用過程中的工作量。 ctypes 的使用很簡單,只需熟悉 python 封裝與 C 中的對應關系即可。以下用一個簡單的例子來說明:
from ctypes import * #導入ctypes模塊
libc = cdll.LoadLibrary("libc.so.6") #載入libc動態庫
str = c_char_p(' Hello World! ') #使用char *在ctypes中的對應封裝c_char_p,相當於char* str=」Hello World!」
libc.printf(「yell: %s\n」, str ) #調用printf函數
ctypes的功能當然遠不止這些,有興趣的同學可以參考這里 http://docs.python.org/library/ctypes.html
使用Python 的擴展( Extending )機制
ctypes很方便地可以調用 C 的動態庫,但是對 C++ 編譯的動態庫,調用起來很困難。這種情況利用 Python 的 Extending 機制就可以解決。 Python 提供了一套完整的框架來使用 C/C++ 編寫擴展庫,可以很靈活的開發 C++ 擴展模塊。這種方法的缺點是工作量比較大,需要為每一個方法編寫介面,這里不做詳細介紹,可以參考: http://docs.python.org/extending/extending.html#writing-extensions-in-c
那麼有什麼辦法可以高效的調用C++ 動態庫呢,答案是 SWIG 。
使用SWIG 生成擴展模塊
上面提到了Python 的擴展機制,缺點是工作量比較大,這里介紹一個工具 SWIG 。 SWIG 是一種簡化腳本語言與 C/C++ 介面的開發工具,通過包裝和編譯 C 語言程序來達到與腳本語言通訊目的的工具。它正是基於 Python 的擴展機制,自動生成介面文件,再編譯成可以被 Python 調用的動態庫擴展模塊。
使用SWIG 生成擴展模塊分為以下幾步:
將需要調用的代碼編譯成目標文件(.o) ;
用SWIG 讀取編寫描述文件 (.i) ,生成介面文件 (.cxx) ;
將介面文件編譯為目標文件(.o) ;
將介面文件的目標文件和原代碼段的目標文件一起編譯成動態庫 ;
假設有如下文件
swig_ex.cpp 需要轉換成擴展庫的原始代碼,包含一個int fact(int) 函數
swig_ex.h 原始代碼的頭文件
swig_ex.i SWIG描述文件
swig_ex.i是一個描述文件,有 SWIG 自己的語法,比較簡單,內容如下:
%mole swig_ex
%{
#define SWIG_FILE_WITH_INIT
#include "swig_ex.h"
%}
int fact(int n);
再寫一個Makefile 來把這些文件編譯成動態庫 :
all: swig_ex.o swig_ex_wrap.o _swig_ex.so
swig_ex.o: swig_ex.cpp swig_ex.h #編譯源文件
g++ -fPIC -c swig_ex.cpp
swig_ex_wrap.o: swig_ex.i swig_ex.o #根據 SWIG 描述文件 (.i) 生成介面文件 (.cxx) ,再編譯之
swig -c++ -python swig_ex.i
g++ -O2 -fPIC -c swig_ex_wrap.cxx -I/home/work/linyi/autoframe/tool/python/include/python2.6/
_swig_ex.so: swig_ex_wrap.o #將目標文件打包成動態庫
g++ -shared swig_ex.o swig_ex_wrap.o -o _swig_ex.so
.PHONY: clean
clean:
rm -rf swig_ex_wrap.* swig_ex.py _swig_ex.so
編譯好以後會有一個so 和 py 文件,寫一個 setup.py 把他們安裝到 python 目錄就可以和其他模塊一樣被 python 調用了:
Import swig_ex
swig_ex.fact(10)
參考文檔地址:http://www.swig.org/Doc1.3/SWIGDocumentation.html
原始但有效的方法
除了上面這些方法,在Python 中借用 C/C++ 代碼最原始有效的方法就是將代碼編譯成可執行程序,從 Python 里用 Popen 方法來調用獲取輸出。這種方法簡單有效,缺點是不夠靈活,有比較大的局限性,不過在很多情況下也已經足夠了。
pipe = os.popen('./tool –a %s –b %s' % (「hello」, 「world」))
re = pipe.read()
其他方法
以上這些方法基本上已經能滿足Python 調用 C/C++ 的需求了,此外還有一些方法,例如使用 Boost.Python ,使用 Pyrex ,這些方法都能提供 Python 與 C/C++ 的交互。
總結
在Python 中引用 C/C++ 模塊的方法較多,根據需要從中選擇恰當的方法可以減少很多工作量。
在Python 中引用 C/C++ 模塊彌補了 Python 腳本測試框架的很多不足,在提高代碼復用率的同時,模塊的性能也大大提高。
② python怎麼使用cython
1. Cython是什麼?
它是一個用來快速生成Python擴展模塊(extention mole)的工具
語法是Python和c的混血
Cython作為一個Python的編譯器,在科學計算方面很流行,用於提高Python的速度,通過OpenMPI庫還可以進行吧並行計算。
2. Cython安裝(Windows)
我的環境是win7 x64, python27, vs2010
安裝的基礎是有一個c編譯器(這里以vs2010為例)
從http://cython.org下載安裝包,解壓到一目錄,進入該目錄,在cmd命令行中執行
python setup.py install
註:執行過程可能遇到問題:Windows下pip安裝包報錯:Microsoft Visual C++ 9.0 is required Unable to find vcvarsall.bat
解決方案:下載Microsoft Visual C++ Compiler for Python 2.7,點擊直接安裝即可。
3. 例子
例3.1:入門
創建hello.pyx,內容如下
def say_hello():
print "Hello World!"
創建setup.py,內容如下
from distutils.core import setup
from Cython.Build import cythonize
setup(name = 'Hello world app',
ext_moles = cythonize("hello.pyx"))
編譯Cython代碼
step1: 把.pyx文件被Cython便以為.c文件
step2: 把.c文件編譯為可導入的使用模塊.so(Windows下為.pyd)文件
1
2
python setup.py build
python setup.py install
註:可能出現問題:Unable to find vcvarsall.bat
原因:Python 2.7 會搜索 Visual Studio 2008.如果你電腦上沒有這個版本的話就會報錯。
如果裝的是vs2010,那麼在cmd命令行中執行
1
SET VS90COMNTOOLS=%VS100COMNTOOLS%
如果裝的是vs2010,那麼在cmd命令行中執行
1
SET VS90COMNTOOLS=%VS110COMNTOOLS%
執行
1
2
3
>>> import hello
>>> hello.say_hello()
Hello World!例3.2 通過靜態類型提高速度
在Cython中可以通過標記靜態類型來提高速度,凡是標記為靜態類型的部分都會將動態語言類型變為簡單的c代碼,從而提速。
但是如果濫用靜態類型,會降低可讀性,甚至因類型設置不當導致錯誤類型檢查造成速度降低。
例3.2.1 靜態類型變數
Python原生態代碼
compute.pyx
def f(x):
return x ** 2 - x
def integrate_f(a, b, N):
s = 0
dx = (b - a) / N
for i in range(N):
x += f(a + i * dx)
return s * dx
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = 'Hello world app',
ext_moles = cythonize("compute.pyx"),
)
test.py
import compute
import time
starttime = time.clock()
compute.integrate_f(3.2, 6.9, 1000000)
endtime = time.clock()
print "read: %f s" %(endtime - starttime)
執行
1
2
3
python setup.py build
python setup.py install
python test.py
結果
1
read: 0.332332 s
使用靜態變數替換後的代碼
compute2.pyx
def f(double x):
return x ** 2 - x
def integrate_f(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b - a) / N
for i in range(N):
s += f(a + i * dx)
return s * d
setup2.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = 'Hello world app',
ext_moles = cythonize("compute2.pyx"),
)
test2.py
import compute2
import time
starttime = time.clock()
compute2.integrate_f(3.2, 6.9, 1000000)
endtime = time.clock()
print "read: %f s" %(endtime - starttime)
執行
1
2
3
python setup.py build
python setup.py install
python test.py
結果
1
read: 0.109200s
結論
該測試用例,使用靜態類型速度是不使用靜態類型的3倍。
例3.2.2 靜態類型函數
把compute2.pyx中的函數變為
cdef double f(double x):
return x ** 2 - x
def integrate_f(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b - a) / N
for i in range(N):
s += f(a + i * dx)
return s * dx
結果
1
read: 0.084859 s
結論:比例子3.2.1速度又快了
例3.3 調用C函數
cdef extern from "math.h":
double sin(double)
double cos(double)
cpdef double Sin(double x):
return sin(x)
cpdef double Cos(double x):
return cos(x)
cpdef: 對於Python可使用的函數使用(為了使得在以後的Python程序中調用Sin,Cos函數,用cpdef,而不用cdef)
cdef: 對於C可使用的函數使用
請注意,上面的代碼聲明了 math.h 里的函數,提供給 Cython 使用。C編譯器在編譯時將會看到 math.h 的聲明,但 Cython 不會去分析 math.h 和單獨的定義。
③ python編譯C擴展報錯
C和Python介面的地方應該沒什麼泄露。
關鍵是你現在是用C,那所有內存分配的地方都有可能泄露唄。 實在不行可以Jython,或者上面提到的Cython
④ 如何編譯Python使之成為可執行程序
Python是一個強大的工具,可惜不是每個人的計算機裡面都有安裝。當您寫了一個好用的工具。要如何讓那些沒有安裝Python的人使用你的工具呢?
對於這樣一個需要standalone exectuable環境的需求,直到撰寫經驗為止,只看到兩個比較好用且有持續維護的套件。一個是py2exe。另外一個就是本經驗要介紹的PyInstaller。
1
PyInstaller安裝
2
最新版本:PyInstaller 2.0
3
直接「解壓縮」之後即可使用,解壓到您想讓他在的路徑即可
END
PyInstaller配置
1
事先寫好py程序
2
在命令行執行:python Makespec.py --console --onefile NotePad\notepad.py
報錯:Configfile is missing or unreadable. Please run Configure.py before building
3
在命令行執行:Configure.py
報錯:Python 2.6+ on Windows support needs pywin32,Please install http://sourceforge.net/projects/pywin32/
4
安裝最新版本的 pywin32-217.win32-py2.7.exe
END
PyInstaller使用
命令行中運行
目錄切換到PyInstaller的安裝目錄「E:\pyinstaller-1.5\pyinstaller-1.
在PyInstaller的安裝目錄下新建一個文件夾(比如NotePad), 然後將要轉換的py腳本放到文件夾里(notepad.py)
E:\pyinstaller-1.5\pyinstaller-1.5>python Makespec.py --console --onefile NotePad\notepad.py
E:\pyinstaller-1.5\pyinstaller-1.5>python Build.py NotePad\notepad.spec
驗證exeE:\pyinstaller-1.5\pyinstaller-1.5>
E:\pyinstaller-1.5\pyinstaller-1.5\NotePad\dist\notepad.exe 0 0 100(成功)
查看生成的文件,生成的中間文件spec
查看生成的文件,生成的最終文件exe
END
注意事項
在轉換之前要確保py程序可以正常通過
如果轉換過程中出現什麼錯誤,用搜索引擎搜索解決一下
⑤ 如何使用cython編譯擴展
先是安裝Cython。由於我只有Windows,所以就只介紹這個平台。
英文的說明可以看《InstallingOnWindows》,共有2步:
一、安裝MinGW。現在SF已不提供完整安裝版了,只能下載在線安裝版。由於Cython也支持C++,所以我也勾選了g++編譯器。
裝好後把MinGW目錄/bin加入PATH環境變數,並保證gcc --version可以正確執行。
接著去Python目錄\Lib\distutils下添加一個distutils.cfg文件,內容如下:
[build]
compiler = mingw32
實際上這最後一步也可不做,但每次編譯都需要加一個-c參數來指定編譯器。
二、安裝Cython。
我是直接下載exe版本的,直接運行即可。Python 2.4可能還要做些額外處理,我沒有這個版本,沒法測試。
接著就可以來測試了,先來寫個hello world。
hw.py:
def hi():
print "Hello World"
setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_moles = [Extension("hw", ["hw.py"])]
)
然後運行這段代碼進行編譯:
setup.py build_ext --inplace
這就生成了很多文件,其中hw.pyd就是生成的C擴展了。
接著測試一下:
>>> from hw import hi
>>> hi()
Hello World
然後來測試下性能:
csigma.py和pysigma.py:
def sigma(n):
a = 0
for i in xrange(n):
a += i
return a
測試腳本:
from timeit import Timer
print Timer('sigma(10000)','from csigma import sigma').timeit(10000)
print Timer('sigma(10000)','from pysigma import sigma').timeit(10000)
⑥ cython編譯為可執行文件,目標機器上不用安裝Python環境就可以執行
本來就是腳本語言,要做窗口程序的話用C#,VB,再不用易語言也可以
python,lua之類的這方面都有各種弊端
再看看別人怎麼說的。
⑦ 怎樣查看cython是否安裝成功
使用Cython實現混編
1 載Cython用Python setup.py install進行安裝
2 實例
① 創建helloworld目錄創建helloworld.pyx,內容:cdef extern from"stdio.h": extern int printf(const char *format, ...) def SayHello(): printf("hello,world\n")
② 編譯便利用pythonDistutils
helloworld目錄創建Setup.py,內容:from distutils.core import setupfrom distutils.extension import Extensionfrom Cython.Build import cythonize setup( name = 'helloworld', ext_moles=cythonize([ Extension("helloworld", ["helloworld.pyx"]), ]),) 編譯:python Setup.py build安裝:python Setup.py install安裝build/lib.???目錄helloworld.pyd拷貝Lib/site-packages註: 我希望測試並希望安裝build/lib.???目錄helloworld.pyd拷貝前目錄 或者importhelloworld前執行腳本:import sys;sys.path.append(pathof helloworld.pyd) ③ 測試:>>>import helloworld >>>helloworld.SayHello() hello,world
⑧ 目前cpython調用C/C++的主流手段是cython么
還可以使用Cython來實現混編
1 下載Cython,用Python setup.py install進行安裝
2 一個實例
① 創建helloworld目錄創建helloworld.pyx,內容如下:cdef extern from"stdio.h": extern int printf(const char *format, ...) def SayHello(): printf("hello,world\n")
② 編譯,最方便的是利用python的Distutils了,
helloworld目錄下創建Setup.py,內容如下:from distutils.core import setupfrom distutils.extension import Extensionfrom Cython.Build import cythonize setup( name = 'helloworld', ext_moles=cythonize([ Extension("helloworld", ["helloworld.pyx"]), ]),) 編譯:python Setup.py build安裝:python Setup.py install安裝後,會將在build/lib.???目錄下生成的helloworld.pyd拷貝到Lib/site-packages註: 有時我們只是希望測試一下,並不希望安裝,這時可以把build/lib.???目錄下的helloworld.pyd拷貝到當前目錄 或者在importhelloworld前執行腳本:import sys;sys.path.append(pathof helloworld.pyd) ③ 測試:>>>import helloworld >>>helloworld.SayHello() hello,world
⑨ IronPython 將python源碼編譯成dll,用python調用報錯ImportError: dynamic mole does not define...
如果你要製作一個python mole名為myjz,那麼就必須定義一個mole入口函數:initmyjz()
⑩ 如何通過cython調用objective-c的類,交叉編譯到IOS上
可以放到項目文件里編譯,就可以防止交叉編譯, 另外include主要需要結構上的管理,也就是通過技術管理的方法進行規避。 如果多人開發團隊任意include, 你通過編譯時的技術手段很難管理好
用pthread實現跨平台。 用cocoa的NSTread或是GCD是無法跨平台的。 你也許會oc的多線程,但在跨平台開發的時候果斷摒棄掉吧。
在我開始使用OpenAphid-Engine的時候,已經有幾種類似的iOS/Android 項目.這些商業項目或者開源項目使用JavaScript實現代碼特性。比如,Titanium 和PhoneGap 允許開發者使用JavaScript開發本地 iOS/Android apps;ngCore 更是可以使用純正的JavaScript構建跨平台的游戲。JavaScript已經成為了編程語言中的佼佼者,也因為更容易學習吸引了眾多開發者參與到這一領域。
怎樣在IOS/Android上使用JavaScript
主要有兩種方法。一種是使用系統的瀏覽器組件(IOS中的UIWebView和Android中的WebView),另一方法就是使用整合好的JavaScript引擎。
使用系統的瀏覽器組件比較容易實現但是更復雜,效率也低。 WebView提供了 addJavascriptInterface 把Java classes注入到JavaScript文本的方法。但是它只支持最原始的幾種數據類型,因此也局限了API設計。並且在Android 2.3模擬器上不穩定,在真機上也會遇到 issue #12987的問題。在IOS上更糟 UIWebView沒有公共的APIs支持JavaScript到Objective-C的交互(你必須使用似有的APIs才能達到與addJavascriptInterface相同的功能)。