Python C扩展将胶囊暴露给ctypes以使用第三方C代码

马修·莫森(Matthew Moisen)

我有一个Python C扩展程序,用于包装专有产品的库。我们公司有大量使用专有产品的C代码。不用使用C扩展在Python中重写它,我想我可以简单地将Capsule返回到Python领域,并允许我的库用户使用ctypes包装一些C函数。

这是有效的方法吗?有更好的吗?

这是一些代码来说明我的方法。

我的Python C扩展:

typedef struct {
    PyObject_HEAD

    Foo *foo; /* The proprietary data structure we are wrapping */
} PyFoo;

/*
* Expose a pointer to Foo such that ctypes can use it
*/
static PyObject PyFoo_capsule(PyFoo *self, PyObject *args, PyObject *kwargs)
{
     return PyCapsule_New(self->foo, "foo", NULL);
}

这是我们团队编写的一些已有的C代码,想从Python调用:

void print_foo(Foo *foo)
{
    Foo_print(foo);
}

在Python中,我们可以使用ctypes包装第三方C代码(我在这里学到):

import pyfoo
import ctypes

foo = pyfoo.Foo()
capsule = foo.capsule()

ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
pointer = ctypes.pythonapi.PyCapsule_GetPointer(
    capsule, 
    ctypes.create_string_buffer("foo".encode())
)

libfoo = ctypes.CDLL('libfoo.so')
libfoo.print_foo.restype = None
libfoo.print_foo.argtypes = [ctypes.POINTER(None)]
libfoo.print_foo(pointer)
维姆·拉夫里森(Wim Lavrijsen)

它将起作用,但是我不喜欢void*对不透明类型使用s的方法,因为任何方法void*都可以,但是在C方面,类型很重要,并且如果指向该类型的指针,您的诊断很可能是段错误(或更糟糕的是)传递了错误的类型。

大多数(自动)联编程序(SWIG,pybind11,C / C ++的cppyy或C的CFFI)都会为不透明的C / C ++生成Python类型,以允许类型匹配。

这是一个cppyy(http://cppyy.org)示例,假设文件foo.h如下:

struct Foo;
struct Bar;

typedef Foo* FOOHANDLE;
typedef Bar* BARHANDLE;

void use_foo(FOOHANDLE);
void use_bar(BARHANDLE);

和一些匹配的库libfoo.so,然后从cppyy中使用时,您只能通过FOOHANDLE参数等传递FOOHANDLE,以便获得干净的Python端回溯,而不是C端崩溃。会话示例:

>>> import cppyy
>>> cppyy.c_include("foo.h")     # assumes C, otherwise use 'include'
>>> cppyy.load_library("libfoo")
>>> foo = cppyy.gbl.FOOHANDLE()  # nullptr; can also take an address
>>> cppyy.gbl.use_foo(foo)       # works fine
>>> cppyy.gbl.use_bar(foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: void ::use_bar(Bar*) =>
    TypeError: could not convert argument 1
>>> 

编辑:对于一些工作,同样可以用ctypes的,如下所示完成的,因此如果你揭露一个C函数返回self->foo一个Foo*你同样可以标注其restype使用Python FOOHANDLE,从而绕过胶囊和其余类型的安全:

import ctypes

libfoo = ctypes.CDLL('./libfoo.so')

class Foo(ctypes.Structure):
    _fields_ = []

FOOHANDLE = ctypes.POINTER(Foo)

class Bar(ctypes.Structure):
    _fields_ = []

BARHANDLE = ctypes.POINTER(Bar)

libfoo.use_foo.restype = None
libfoo.use_foo.argtypes = [FOOHANDLE]

libfoo.use_bar.restype = None
libfoo.use_bar.argtypes = [BARHANDLE]

foo = FOOHANDLE()

libfoo.use_foo(foo)  # succeeds
libfoo.use_bar(foo)  # proper python TypeError

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将第三方共享库与 Python ctypes 集成

来自分类Dev

使用第三方库进行Python部署

来自分类Dev

如何使用Pymysql / Python从第三方API将数据插入数据库?

来自分类Dev

Python:如何安装第三方程序包并使其他团队可以使用

来自分类Dev

Python:扩展从使用工厂方法的第三方程序包返回的类/对象

来自分类Dev

ipdb如何将python调试器带到称为第三方代码的框架

来自分类Dev

如何将第三方Python库导入Bluemix?

来自分类Dev

python模拟第三方模块

来自分类Dev

Python / Django中的第三方API集成

来自分类Dev

删除从第三方安装的python3.9

来自分类Dev

不使用第三方库反转Python中的已知算法

来自分类Dev

使用Python和Mock模拟ReviewBoard第三方库

来自分类Dev

不使用第三方软件包的嵌套for循环的python打印进度

来自分类Dev

如何在Python中使用第三方库?

来自分类Dev

我如何使用 gettext 翻译第三方 python 模块的字符串

来自分类Dev

有没有办法从您插件中的第三方kodi / xbmc插件访问python代码?

来自分类Dev

Python枕头:在将图像发送到第三方服务器之前使图像渐进

来自分类Dev

如何通过已知协议将python程序与第三方程序连接起来?

来自分类Dev

将Webapi暴露给第三方

来自分类Dev

使用请求加载所有第三方脚本或在Python中机械化

来自分类Dev

列出Python文件中使用的所有第三方软件包及其自身功能

来自分类Dev

使用请求加载所有第三方脚本或在Python中机械化

来自分类Dev

通过第三方代码,C# 解密

来自分类Dev

Python:在个人Python包中包含第三方库

来自分类Dev

使用C ++模板包装第三方C代码

来自分类Dev

从第三方Python模块中提取信息?

来自分类Dev

Python覆盖第三方软件包单个文件

来自分类Dev

无需第三方Python模块即可解析日期

来自分类Dev

如何让python的第三方库twisted在sublime中自动完成?

Related 相关文章

  1. 1

    将第三方共享库与 Python ctypes 集成

  2. 2

    使用第三方库进行Python部署

  3. 3

    如何使用Pymysql / Python从第三方API将数据插入数据库?

  4. 4

    Python:如何安装第三方程序包并使其他团队可以使用

  5. 5

    Python:扩展从使用工厂方法的第三方程序包返回的类/对象

  6. 6

    ipdb如何将python调试器带到称为第三方代码的框架

  7. 7

    如何将第三方Python库导入Bluemix?

  8. 8

    python模拟第三方模块

  9. 9

    Python / Django中的第三方API集成

  10. 10

    删除从第三方安装的python3.9

  11. 11

    不使用第三方库反转Python中的已知算法

  12. 12

    使用Python和Mock模拟ReviewBoard第三方库

  13. 13

    不使用第三方软件包的嵌套for循环的python打印进度

  14. 14

    如何在Python中使用第三方库?

  15. 15

    我如何使用 gettext 翻译第三方 python 模块的字符串

  16. 16

    有没有办法从您插件中的第三方kodi / xbmc插件访问python代码?

  17. 17

    Python枕头:在将图像发送到第三方服务器之前使图像渐进

  18. 18

    如何通过已知协议将python程序与第三方程序连接起来?

  19. 19

    将Webapi暴露给第三方

  20. 20

    使用请求加载所有第三方脚本或在Python中机械化

  21. 21

    列出Python文件中使用的所有第三方软件包及其自身功能

  22. 22

    使用请求加载所有第三方脚本或在Python中机械化

  23. 23

    通过第三方代码,C# 解密

  24. 24

    Python:在个人Python包中包含第三方库

  25. 25

    使用C ++模板包装第三方C代码

  26. 26

    从第三方Python模块中提取信息?

  27. 27

    Python覆盖第三方软件包单个文件

  28. 28

    无需第三方Python模块即可解析日期

  29. 29

    如何让python的第三方库twisted在sublime中自动完成?

热门标签

归档