擴展Python模塊系列(一)----開發環境配置


    本系列將介紹如何用C/C++擴展Python模塊,使用C語言編寫Python模塊,添加到Python中作為一個built-in模塊。Python與C之間的交互目前有幾種方案:

1. 原生的Python C/C++ API, 官網有非常詳細的文檔說明

2. boost python,一個C++的編程框架,對官方API進行了封裝,可以方便的用C++擴展Python模塊,省去了很多諸如引用計數的煩惱。 http://www.boost.org/doc/libs/1_64_0/libs/python/doc/html/index.html

3. Cython. Cython其實是一個可以優化Python程序的編譯器,將Python代碼翻譯成C代碼,然后使用C/C++編譯器進行編譯得到pyd(windows)或so(linux),在Python解釋器中可以直接import。這種方法里面的坑有點多,在本系列博客中會介紹到Cython。   http://cython.org/

4. 谷歌最近開源的CLIF項目,同時支持Python2和Python3,目前來說還不太完善。  https://github.com/google/clif

其他的框架。。。。。。

    本篇將介紹如何用官方提供的Python C/C++ API來擴展Python模塊。工欲善其事必先利其器,先講一下如何搭建開發環境(默認已經安裝了Python)。以下為【DEBUG】版的配置:

1. Python版本: Python2.7 32位;   操作系統: Windows7;  IDE: Visual Studio 2015。

2. 配置Library Directories、Additional Include Directories、Link Input

 

 3. 寫一段hello world程序 ,先不糾結語法細節

[test.c]

#include <Python.h>

static PyMethodDef test_methods[] = { NULL, NULL, 0, NULL };

PyMODINIT_FUNC test_init(void)
{
    Py_InitModule3("test", test_methods, "Common test Written in C.");
}

[Souce.cpp]

#include <Python.h>

PyMODINIT_FUNC test_init();

int main()
{
    Py_Initialize(); 
    test_init();
    return 0;
}

 

然后編譯,很大可能會出現Link時找不到解析符號以及無法找到python27_d.lib,這主要是pyconfig.h里代碼的一些宏導致的。

 

1)找到python2.7/include/pyconfig.h,並找到

#ifdef _DEBUG
#define Py_DEBUG
#endif

修改為

#ifdef _DEBUG
//#define Py_DEBUG
#endif

2)Configuration Properties->C/C++->Preprocessor->Preprocessor Definitions添加MS_NO_COREDLL或Py_NO_ENABLE_SHARED

原因解釋:

1)

在pyconfig.h中:

#ifdef _DEBUG
#define Py_DEBUG
#endif

在object.h中有以下定義:

/* Py_DEBUG implies Py_TRACE_REFS. */
#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
#define Py_TRACE_REFS
#endif

在modesupport.h中

#ifdef Py_TRACE_REFS
 /* When we are tracing reference counts, rename Py_InitModule4 so
    modules compiled with incompatible settings will generate a
    link-time error. */
 #if SIZEOF_SIZE_T != SIZEOF_INT
 #undef Py_InitModule4
 #define Py_InitModule4 Py_InitModule4TraceRefs_64
 #else
 #define Py_InitModule4 Py_InitModule4TraceRefs
 #endif
#endif

 

所以當定義了Py_DEBUG,就會導致Py_InitModule4重命名為Py_initModule4TraceRefs,而lib中沒有此符號,所以導致了鏈接錯誤。故而注釋掉#define Py_DEBUG這一行即可。

2)找不到python27_d.lib問題

同樣在pyconfig.h中:

/* For Windows the Python core is in a DLL by default.  Test
Py_NO_ENABLE_SHARED to find out.  Also support MS_NO_COREDLL for b/w compat */
#if !defined(MS_NO_COREDLL) && !defined(Py_NO_ENABLE_SHARED)
#    define Py_ENABLE_SHARED 1 /* standard symbol for shared library */
#    define MS_COREDLL    /* deprecated old symbol */
#endif /* !MS_NO_COREDLL && ... */

/*  All windows compilers that use this header support __declspec */
#define HAVE_DECLSPEC_DLL

/* For an MSVC DLL, we can nominate the .lib files used by extensions */
#ifdef MS_COREDLL
#    ifndef Py_BUILD_CORE /* not building the core - must be an ext */
#        if defined(_MSC_VER)
            /* So MSVC users need not specify the .lib file in
            their Makefile (other compilers are generally
            taken care of by distutils.) */
#            ifdef _DEBUG
#                pragma comment(lib,"python27_d.lib")
#            else
#                pragma comment(lib,"python27.lib")
#            endif /* _DEBUG */
#        endif /* _MSC_VER */
#    endif /* Py_BUILD_CORE */
#endif /* MS_COREDLL */

可以看到如果沒有定義MS_NO_COREDLL和Py_NO_ENABLE_SHARED時,會定義MS_COREDLL,然后在DEBUG模式下會加載python27_d.lib。所以在Preprocessor Definitions中定義MS_NO_COREDLL即可解決。

4. 編譯&鏈接錯誤解決之后,可以正常運行。

上面的例子中,test.c定義了一個模塊test,在Source.cpp中初始化了該模塊。下一節將用一個例子來詳細介紹使用Python C/C++ API擴展Python模塊。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM