python怎么作为c语言的扩展

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python怎么作为c语言的扩展相关的知识,希望对你有一定的参考价值。

  1.环境配置,python3.2装好,编译器我直接用的devcpp的编译器(原因是直接安装就可以,其它的编译器我还不会用),将devcpp的bin目录添加到环境变量path中。
  2.准备好your_module.c文件,这是你自己的C语言写的扩展程序,确保你的your_module.c符合python和C的接口要求。
  3.python提供了distutils模块用来方便地将c文件转变成pyd文件,也是笔者比较推荐的方法。准备好your_module.c文件后,在同一目录下创建steup.py文件,文件内容如下:
  
  from distutils.core import setup, Extension
  
  module1 = Extension(\'your_module_name\',
  sources = [\'demo.c\'])
  
  setup (name = \'PackageName\',
  version = \'1.0\',
  description = \'This is a demo package\',
  ext_modules = [module1])
  注意\'your_module_name\'要跟C文件中PyInit_module函数的\'module\'一样,否则在后续的步骤中会出错。
  4.建立steup.bat文件,内容只有两行:
  python.exe setup.py build -c mingw32
  pause
  5.运行steup.bat文件。
  6.如果没有错误,在build\\lib.win32-3.2下找到生成的pyd文件,放置到PYTHONPATH的目录中即可被import调用,到此大功告成。注意,python寻找pyd文件不是在sys.path中找,而是在PYTHONPATH指定的目录中找。
参考技术A Python是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年。
Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议[1] 。
Python语法简洁清晰,特色之一是强制用空白符(white space)作为语句缩进。
Python具有丰富和强大的库。它常被昵称为胶水语言,能够把用其他语言制作的各种模块(尤其是C/C++)很轻松地联结在一起。常见的一种应用情形是,使用Python快速生成程序的原型(有时甚至是程序的最终界面),然后对其中[2] 有特别要求的部分,用更合适的语言改写,比如3D游戏中的图形渲染模块,性能要求特别高,就可以用C/C++重写,而后封装为Python可以调用的扩展类库。需要注意的是在您使用扩展类库时可能需要考虑平台问题,某些可能不提供跨平台的实现。
在python中扩展c语言模块可以总结为以下几步:
1.首先,编写包含py接口的c源文件,称为wrap.c。这一步可以使用swig带过。 例如:swig -python foo.i
2.接着,对wrap.c进行编译,生成XX.so。这一步可以使用 distutils带过。如果要用 distutils的话,则需要首先编写一个py脚本。示例:setup(name = 'example', version = '1.0', ext_modules = [Extension('example', ['wrap.c','example.c'])]) 注意:句子中的list不仅不要包含wrap源文件,还要包含函数的原始源文件
3.上一步的so文件便是最终可以使用的库文件,把该文件放入py的lib中或者当前目录,即可导入c语言扩展模块进行使用。如果之前用过swig,还要把相应的so文件移入模块文件夹中并在文件名前加上_。示例: cp printf.so /usr/lib64/python2.7/site-packages/_printf.so
参考技术B 2.准备好your_module.c文件,这是你自己的C语言写的扩展程序,确保你的your_module.c符合python和C的接口要求。
3.python提供了distutils模块用来方便地将c文件转变成pyd文件,也是笔者比较推荐的方法。准备好your_module.c文件后,在同一目录下创建steup.py文件,文件内容如下:

from distutils.core import setup, Extension

module1 = Extension('your_module_name',
sources = ['demo.c'])

setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1])
注意'your_module_name'要跟C文件中PyInit_module函数的'module'一样,否则在后续的步骤中会出错。
4.建立steup.bat文件,内容只有两行:
python.exe setup.py build -c mingw32
pause
5.运行steup.bat文件。
6.如果没有错误,在build\lib.win32-3.2下找到生成的pyd文件,放置到PYTHONPATH的目录中即可被import调用,到此大功告成。注意,python寻找pyd文件不是在sys.path中找,而是在PYTHONPATH指定的目录中找。

C语言 V信 fsdw852
参考技术C

Python 和 C++有相似的编程理念,两者又有很好的互补性。C++的准标准库:Boost, 通过boost.python库提供了对Python语言的全面支持。

boost.python库全面支持c++和python的各种特性,包括C++到Python的异常转换、默认参数、关键字参数、引用和指针等等,让C++和Python可以近乎完美对接:用C++很容易地为Python编写扩展模块,也可以很容易地在C++代码中执行Python程序。

使用boost.python库通常需要这些步骤:

    安装Python环境,一般建议使用Python 2.x版本,比较稳定,且有非常丰富的第三方库;

    编译boost.python库,可以从boost的官方文档中参考获取编译方式。

    使用python库, 在C++代码中包含头文件<boost/python.hpp>,并使用名字空间boost::python 

使用boost.python 有这些基本的用法:

    嵌入python语句——这是最简单的用法。只需要调用Python API函数 Py_Initialize()启动Python解释器,然后用object类来封装Python中的类以及执行Python语句

    扩展Python——这是比较高级的用法,可以用来编写扩展模块

总结

以上材料可以从boost的官方文档中得到详细的介绍(http://www.boost.org/),推荐中文书籍《Boost程序库完全开发指南》可以作为很好的补充。

嵌入Python这种方式可以使我们在C++中直接执行已经写好的Python脚本;扩展Python库的方式则可以构建c++和Python混合的软件系统。

扩展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 2017。

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模块。

 

以上是关于python怎么作为c语言的扩展的主要内容,如果未能解决你的问题,请参考以下文章

python源码剖析

python C语言扩展之简单扩展-使用ctypes访问C代码

使用C语言扩展Python3

C语言中的感叹号是怎么用的

『Python CoolBook』C扩展库_其六_从C语言中调用Python代码

Python书读千遍不如手敲一行