python pyrex windows 編譯C可執行文件

python寫成py文件通過處理轉化成pyx文件,以及函數說明文件pyi使用pyrexc.py編譯成對應模塊的c和h文件
而後寫一個main的cpp文件,使用cmake產生vs工程,使用incredBuild編譯工程。
如下是一個實例:
python原腳本,功能是更改目錄下hcpp文件的修改時間,本地調試修改時間以後致使代碼編譯時間戳錯亂,故寫了一個py腳本
#!/bin/python
#coding=gbk

import sys,os,time,re

def walk_dir(dir):
    timenow = time.time()
    ncntnum = 0
    for root, dirs, files in os.walk(dir, True):
        for name in files:
            filename = os.path.join(root,name)
            mat = re.search('[.](h|cpp|c|hpp)',filename)
            if mat:
                filechgtime = os.path.getmtime(filename)
                if filechgtime > timenow:
                    os.utime(filename,(timenow,timenow))
                    print '已修改:',filename
                    ncntnum += 1
                    
    print '修改數:',ncntnum

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print '添加參數:目錄'
    else:
        walk_dir(sys.argv[1])

文件名爲chgFileTM.py,直接拷貝爲chgFileTM.pyx,將pyx文件修改以下:python

#!/bin/python
#coding=gbk

import os,time,re

def walk_dir(dir):
    timenow = time.time()
    ncntnum = 0
    for root, dirs, files in os.walk(dir, True):
        for name in files:
            filename = os.path.join(root,name)
            mat = re.search('[.](h|cpp|c|hpp)',filename)
            if mat:
                filechgtime = os.path.getmtime(filename)
                if filechgtime > timenow:
                    os.utime(filename,(timenow,timenow))
                    print '已修改:',filename
                    ncntnum += 1
                    
    print '修改數:',ncntnum

    
cdef public void c_walk_dir(char* pfir):
    try:
        walk_dir(pfir)
    except Exception , e:
        print e

添加一個pyrex格式的函數實現,調用+異常
chgFileTM.pyi文件,函數說明:

cdef extern void (c_walk_dir(char* pfir))linux

確認python安裝了pyrex
執行pyrexc.py chgFileTM.pyx
生成了chgFileTM.h以及chgFileTM.c,若是提示錯誤的話通常是pyx文件空格和tab混用報錯,直接用4個空格替換全部tab就行
能夠參考下函數的調用,test.cpp
#include "chgFileTM.h"
#include <iostream>
#include "Python.h"
#include "structmember.h"

int main(int argc, char *argv[])
{
 if(argc <= 1)
 {
  std::cout<<"參數:目錄"<<std::endl;
  return 1;
 }
 try
 {
  Py_Initialize();

  initchgFileTM(); // 這個地方的函數名字爲init加上模塊名,就是原來那個py文件的名字
  c_walk_dir(argv[1]);

  Py_Finalize();
 }
 catch(...)
 {
  std::cout<<"有異常"<<std::endl;
 }
 
 return 0;
}

ps:pyrex的默認處理有問題,編譯得到的.h文件不包含#include "Python.h"的引入定義,能夠手動修改.h文件也能夠修改pyrex的源代碼,都是python代碼,修改位置以下:
python安裝目錄\Lib\site-packages\Pyrex\Compiler\ModuleNode.py
generate_extern_c_macro_definition函數下面添加
def generate_python_h_include(self, code):
        code.putln('#include "Python.h"')
generate_h_code函數,self.generate_extern_c_macro_definition(h_code)下面添加self.generate_python_h_include(h_code)
OK了,若是執行錯誤,那仍是空格和tab的問題,替換下就行,再次執行 yrexc.py chgFileTM.pyx

目前:代碼準備工做已經完成,剩下的就是自動編譯的問題了
考慮下咱們的編譯平臺,下載python源代碼,發現windows下的編譯是用的vs,我用的是vs2008,選擇9.0版本
編譯python版本,只要是主要的文件python pythonw工程,採用release版本吧,獲得python的dll及lib等文件
把編譯得到的dll及lib文件拷貝到python安裝目錄的libs及dlls等目錄,將python的dlls目錄添加到path路徑

自動編譯採用cmake  incredBuild,要否則本身寫cl的編譯腳本,比較麻煩
好,編譯環境的問題解決了,上我寫的自動化腳本
#!D:/GNU/MSYS/bin/sh.exe
#edit cmake

if [ $# != 1 ] ; then 
        echo "USAGE: cmake.sh proj" 
exit 1;
fi 

makefilelist=CMakeLists.txt
PROJECT_NAME=$1
FILE_NAME=`ls *.[ch]*`

rm -f $makefilelist
#工程設置
echo -e 'PROJECT(' $PROJECT_NAME ')' '\n' >> $makefilelist
  
#不用修改設置
echo -e 'SET(VC9_DIR $ENV{VC9_DIR})' '\n'\
  'SET(PYTHON_DIR $ENV{PYTHON_DIR})' '\n'\
  'SET(CMAKE_C_COMPILER  "${VC9_DIR}/bin/cl.exe")' '\n'\
  'SET(CMAKE_CXX_COMPILER  "${VC9_DIR}/bin/cl.exe")' '\n'\
  'SET(LIBRARY_OUTPUT_PATH  "${PROJECT_BINARY_DIR}")' '\n'\
  'include_directories ("${PYTHON_DIR}/include" )' '\n'\
  'link_directories ("${PYTHON_DIR}/libs" "${PYTHON_DIR}/Lib" )' '\n' >> $makefilelist
  
#庫和exe設置
echo -e 'add_executable('$PROJECT_NAME $FILE_NAME') \n' >> $makefilelist
  
#執行腳本
rm -fr build
mkdir build
cd build

echo 'start cmake'
cmake -G  "Visual Studio 9 2008" ..

echo 'start build'
echo -e BuildConsole.exe $PROJECT_NAME /build /cfg=\"Release\|Win32\" '\n'\
  rm -f ../$PROJECT_NAME.exe '\n'\
  cp Release/$PROJECT_NAME.exe ../$PROJECT_NAME.exe '\n'\
  pause '\n'\
  exit > build.bat

start build.bat
cd ..

#刪除腳本
rm -f $makefilelist

使用的是MSYS的shell模擬器執行,若是沒有能夠考慮安裝一下,使用的時候
sh cmake.sh 工程名,直接指定了完成的exe的文件名
通常能自動完成,若是不能,使用vs2008手動編譯下看看

好比執行sh cmake.sh chgFileTM
在目錄獲得chgFileTM.exe
如今直接執行是沒問題的,可是離開了擁有python的機器就不行了
拷貝python安裝目錄DLLS目錄下的文件到沒安裝上的機器就好了
固然要是想簡單的話寫個打包工具也能夠

以上僅僅是windows的作法,在linux,基本都有python,直接的執行效率也不錯,以爲也不必製做打包工具了。
相關文章
相關標籤/搜索