标签: python-c-extension

我可以在扩展Python时使用C++功能吗?

Python手册说您可以在C和C++中为Python创建模块.使用C++时,您可以利用类和模板之类的东西吗?它不会与其他库和解释器产生不兼容性吗?

c c++ python python-c-api python-c-extension

5
推荐指数
1
解决办法
539
查看次数

使用 pyx/pxd 文件中的函数工厂为 C 库生成 cython 函数包装器

我正在重新评估将外部 C 库包装到 Python 中的不同方法。我很久以前就选择使用简单的 Python C API,它快速、简单、独立,而且正如我认为的那样,它是面向未来的。然后我偶然发现了PyPy,它显然不打算支持 CPython API,但将来可能会成为一个有趣的替代方案......因此我正在寻找一个更高级别的入口点。ctypes速度很慢,所以现在我回到了cython,它似乎正在努力支持 PyPy。

我的库有许多具有相同签名的函数,因此我广泛使用 C 预处理器宏来生成 Python 模块。我认为这在 cython 中会变得更加舒适,因为我可以访问整个 Python 语言。但是,我在为函数包装器编写工厂时遇到问题:

import cython
from numpy cimport ndarray, double_t

cimport my_c_library

cdef my_c_library.data D

ctypedef double_t DTYPE_t

cdef parse_args(ndarray[DTYPE_t] P, ndarray[DTYPE_t] x, ndarray[DTYPE_t] y):
    D.n = P.size
    D.m = x.size
    D.P = <double*> P.data
    D.x = <double*> x.data
    D.y = <double*> y.data

def _fun_factory(name):
    cpdef fun(ndarray[DTYPE_t] P, ndarray[DTYPE_t] x, ndarray[DTYPE_t] y):
        parse_args(P, x, y)
        getattr(my_c_library, name)(&D) …
Run Code Online (Sandbox Code Playgroud)

python numpy cython python-c-extension

5
推荐指数
1
解决办法
1492
查看次数

优化boost :: python :: object实例

我最近开始使用Boost的Python库来包装一个相当大的C++库的一部分.

很偶然,我发现Boost Python创建的每个Python对象至少比Python List的大小要大.

简单的类型

使用noddy_NoddyType例如C-Python的API文档,我可以很容易地露出新对象类型实例,noddy_NoddyObject.

使用原始C-Python API,这与自定义Python对象一样小而简单: -

>>> import noddy, sys

>>> print sys.getsizeof( noddy.Noddy )   # PyTypeObject size?
872
>>> print sys.getsizeof( noddy.Noddy() ) # PyObject size
16
Run Code Online (Sandbox Code Playgroud)

并与基础对象进行比较: -

>>> print sys.getsizeof( object )
872
>>> print sys.getsizeof( object() )
16
Run Code Online (Sandbox Code Playgroud)

这是预期的,但是当我noddy_NoddyObject使用Boost Python 公开时呢?

>>> print sys.getsizeof( noddy.Noddy )
904
>>> print sys.getsizeof( noddy.Noddy() )
80
Run Code Online (Sandbox Code Playgroud)

说什么?!!那不太理想......对象实例比它们需要的大5倍!

(这在非64位计算机上会有所不同.)

在Boost Python维基上,有一些额外膨胀的解释: - …

c++ python numpy boost-python python-c-extension

5
推荐指数
0
解决办法
528
查看次数

如何在Python C/C++扩展之间共享一个全局C/C++变量?

我几乎完全用C++编写了一个Python包.这样做的原因是因为我想手动包装现有的C++库,但这与此无关.

这个Python包由许多不同的扩展模块组成,所有这些模块都是在'setup.py'脚本中用distutils编译的.这些扩展模块可以是相互关联的,在这种情况下,我通过将共享库传递给Extension构造函数来链接它们.要清楚,假设我有两个Python C++模块,A和B,其中B使用A中定义的函数.这些通常编译成A.so和B.so. 由于B使用A中定义的函数,因此我像往常一样编译A模块,然后将':A.so'作为库传递给B模块的Extension构造函数中的libraries关键字.(':'让g ++处理这个事实,即库不以通常的'lib'前缀开头.)这适用于链接函数和类.

我的问题如下:我在A中定义了一些全局C++变量.虽然我所描述的内容允许B访问A中的函数,但它实际上似乎创建了A中定义的任何全局数据的COPY.这是一个真正的问题为了我.

在我看来,该问题基本上类似于在共享库中具有全局变量,如此和其他地方所讨论的.该解决方案以及我在网上找到的其他解决方案似乎无法解决问题.

任何帮助将非常感谢!

编辑:忘记提及,是的,我的全局变量被声明为extern.

c c++ python shared-libraries python-c-extension

5
推荐指数
1
解决办法
2173
查看次数

Doc扩展在C-extension和Python3上使用UnicodeDecodeError失败

我很难让我的测试框架适用于Python2和Python3的C扩展模块.我喜欢运行我的文档字符串doctest以确保我没有向用户提供不良信息,所以我想在doctest测试中运行.

我不相信我的问题的根源是文档字符串本身,而是doctest模块如何尝试读取我的扩展模块.如果我运行doctestPython2(在针对Python2编译的模块上),我得到了我期望的输出:

$ python -m doctest myext.so -v
...
1 items passed all tests:
98 tests in myext.so
98 tests in 1 items.
98 passed and 0 failed.
Test passed.
Run Code Online (Sandbox Code Playgroud)

但是,当我使用Python3时,我得到了一个UnicodeDecodeError:

$ python3 -m doctest myext3.so -v
Traceback (most recent call last):
...
  File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/doctest.py", line 223, in _load_testfile
    return f.read(), filename
  File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/codecs.py", line 301, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte …
Run Code Online (Sandbox Code Playgroud)

python doctest python-c-extension python-3.x

5
推荐指数
1
解决办法
441
查看次数

PyErr_CheckSignals 未拾取信号

我有一个 C 扩展,它实现了 LRU 缓存https://github.com/pbrady/fastcache。我最近注意到,在一个大量使用缓存的应用程序(SymPy)中,超时信号丢失,而应用程序继续运行。仅当使用我的 C 扩展而不是使用纯 Python LRU 缓存(即 functools.lru_cache)时才会发生这种情况https://github.com/pbrady/fastcache/issues/26

我在例程中添加了对 PyErr_CheckSignals() 的调用,信号丢失的频率降低了,但这种情况仍然会发生。请注意,在调用期间,缓存将调用 PyObject_Hash、PyDict_Get/Set/DelItem 和 PyObject_Call(在未命中的情况下)。

这是 SymPy 代码的相关片段(超时是一个整数):

def _timeout(self, function, timeout):
    def callback(x, y):
        signal.alarm(0)
        raise Skipped("Timeout")
    signal.signal(signal.SIGALRM, callback)
    signal.alarm(timeout)  # Set an alarm with a given timeout
    function()
    signal.alarm(0)  # Disable the alarm    enter code here
Run Code Online (Sandbox Code Playgroud)

有什么东西会覆盖信号吗?如果是这样,我该如何解决这个问题?

c python signals python-c-api python-c-extension

5
推荐指数
1
解决办法
826
查看次数

是否可以预编译(预构建/预安装)Python C/C++ 扩展?

我正在开发一个大型 Python 项目,其中包含多个 C/C++ 扩展。目前,每次我想让代码在新机器上运行时,我都必须从存储库下载所有内容,然后运行python setup.py install几次,每个扩展一次......并且假设计算机安装了 C 编译器 - 如果事实并非如此,这还需要一两个额外的步骤。

有什么方法可以预编译所有 C 扩展,以便当我将存储库下载到新机器时,一切都可以开箱即用,而无需单独安装所有这些子组件?我知道这在不同平台上可能无法正常工作(或根本无法工作?),但假设我在 64 位 Windows 8 计算机上预编译了一些内容,并想将其安装在另一台 64 位 Windows 8 计算机上 - 是那可能吗?如果是这样,我将如何去做呢?

python python-c-extension

5
推荐指数
1
解决办法
893
查看次数

如何使用 distutils 和/或 setuptools 在 mac os x 上创建 .dylib C 扩展?

我需要使用 distutils (和/或 setuptools)创建一个 C 扩展,它可以在运行时和编译时动态使用(用于不同的目的)。这在 Linux 上不是问题,但在 OS X 上却是问题。默认情况下,distutils 在 OS X 上创建一个“捆绑包”(并将其命名为 .so),它可以在运行时使用,但不能在编译时使用。我需要制作一个 .dylib,它可以在编译时链接到,并且我需要在可以为 PyPI 打包的 setup.py 中执行此操作。

无论我尝试什么,distutils 都会不断创建捆绑包,当我尝试链接该库时,我收到错误。您可以通过在命令行上使用 file 显式检查 distutils 是否创建了捆绑包或动态链接库:

file libA.so
libA.so: Mach-O 64-bit bundle x86_64
Run Code Online (Sandbox Code Playgroud)

以下 cc 命令给了我我想要的:

cc -fPIC -shared source1.o source2.o -o libA.so
file libA.so
libA.so: Mach-O 64-bit dynamically linked shared library x86_64
Run Code Online (Sandbox Code Playgroud)

macos distutils shared-libraries setuptools python-c-extension

5
推荐指数
1
解决办法
1791
查看次数

从Python中返回包含和运行时lib目录

让我们说我想gcc从命令行使用,以编译Python的C扩展.我将这样的调用结构如下:

gcc -o applesauce.pyd -I C:/Python35/include -L C:/Python35/libs -l python35 applesauce.c
Run Code Online (Sandbox Code Playgroud)

我注意到-I,-L-l选项是绝对必要的,否则你会得到类似如下的错误.这些命令告诉gcc在哪里查找headers(-I),在哪里查找静态库(-L),以及实际使用哪个静态库(python35实际转换为libpython35.a).

现在,显然很容易获得libsinclude你的机器一样的目录,因为如果你不想让它们永远不会改变.但是,我正在编写一个gcc从命令行调用的程序,其他人将使用该程序.发生此调用的行看起来像这样:

from subprocess import call
import sys
filename = applesauce.c
include_directory = os.path.join(sys.exec_prefix, 'include')
libs_directory = os.path.join(sys.exec_prefix, 'libs')

call(['gcc', ..., '-I', include_direcory, '-L', libs_directory, ...])
Run Code Online (Sandbox Code Playgroud)

但是,其他人将拥有不同的平台和不同的Python安装结构,因此只是加入路径并不总是有效.

相反,我需要Python中的一个解决方案,它将可靠地返回includelibs目录.

编辑:

我查看了该模块distutils.ccompiler,发现了许多有用的函数,它们部分地使用了distutils,但是让我可以自定义我的编译器完全跨平台.唯一的问题是,我需要传递包含和运行时库...

编辑2:

我看了一下distutils.sysconfig,我能够可靠地返回包含所有头文件的'include'目录.我仍然不知道如何获取运行时库.

该 …

python gcc static-libraries python-c-extension

5
推荐指数
2
解决办法
149
查看次数

如何内省Cython C扩展模块中定义的函数

Python的inspect模块似乎无法检查"内置"函数的签名,其中包括C扩展模块中定义的函数,如Cython定义的函数.有没有办法获得你在这样一个模块中定义的Python函数的签名,特别是在Cython中?我希望能够找到可用的关键字参数.

MWE:

# mwe.pyx
def example(a, b=None):                                                                                                                                                       
    pass       
Run Code Online (Sandbox Code Playgroud)

import pyximport; pyximport.install()                                                                                                                                         
import mwe                                                                                                                                                                    
import inspect                                                                                                                                                                

inspect.signature(mwe.example)   
Run Code Online (Sandbox Code Playgroud)

收益率:

Traceback (most recent call last):                                                                                                                                           
  File "mwe_py.py", line 5, in <module>                                                                                                                                      
    inspect.signature(mwe.example)                                                                                                                                           
  File "/nix/store/134l79vxb91w8mhxxkj6kb5llf7dmwpm-python3-3.4.5/lib/python3.4/inspect.py", line 2063, in signature                                                         
    return _signature_internal(obj)                                                                                                                                          
  File "/nix/store/134l79vxb91w8mhxxkj6kb5llf7dmwpm-python3-3.4.5/lib/python3.4/inspect.py", line 1965, in _signature_internal                                               
    skip_bound_arg=skip_bound_arg)                                                                                                                                           
  File "/nix/store/134l79vxb91w8mhxxkj6kb5llf7dmwpm-python3-3.4.5/lib/python3.4/inspect.py", line 1890, in _signature_from_builtin                                           
    raise ValueError("no signature found for builtin {!r}".format(func))                                                                                                     
ValueError: no signature found for builtin <built-in function example>    
Run Code Online (Sandbox Code Playgroud)

在Python 3.4.5和Cython 0.24.1中

python introspection cython python-c-extension

5
推荐指数
1
解决办法
1599
查看次数