简体   繁体   English

Python:SWIG与ctypes

[英]Python: SWIG vs ctypes

In python, under what circumstances is SWIG a better choice than ctypes for calling entry points in shared libraries? 在python中,什么情况下SWIG比ctypes更好的选择是在共享库中调用入口点? Let's assume you don't already have the SWIG interface file(s). 假设您还没有SWIG接口文件。

What are the performance metrics of the two? 两者的性能指标是什么?

I have a rich experience of using swig. 我有使用Swig的丰富经验。 SWIG claims that it is a rapid solution for wrapping things. SWIG声称这是包装物品的快速解决方案。 But in real life... 但是在现实生活中


Cons: 缺点:

SWIG is developed to be general, for everyone and for 20+ languages. SWIG开发为通用的,适用于所有人和20多种语言。 Generally, it leads to drawbacks: 通常,它导致缺点:
- needs configuration (SWIG .i templates), sometimes it is tricky, -需要配置(SWIG .i模板),有时很棘手,
- lack of treatment of some special cases (see python properties further), -缺乏对某些特殊情况的处理(进一步参见python属性),
- lack of performance for some languages. -某些语言缺乏性能。

Python cons: Python缺点:

1) Code style inconsistency . 1) 代码风格不一致 C++ and python have very different code styles (that is obvious, certainly), the possibilities of a swig of making target code more Pythonish is very limited. C ++和python具有非常不同的代码样式(这是显而易见的,当然),因此使目标代码更像Pythonish的可能性非常有限。 As an example, it is butt-heart to create properties from getters and setters. 例如,从getter和setter创建属性是对接。 See this q&a 查看此问答

2) Lack of broad community . 2) 缺乏广泛的社区 SWIG has some good documentation. SWIG有一些很好的文档。 But if one caught something that is not in the documentation, there is no information at all. 但是,如果发现了文档中未包含的内容,则根本没有任何信息。 No blogs nor googling helps. 没有博客,也没有谷歌搜索帮助。 So one has to heavily dig SWIG generated code in such cases... That is terrible, I could say... 因此,在这种情况下,人们不得不大量挖掘SWIG生成的代码...我可以说这太可怕了...

Pros: 优点:

  • In simple cases, it is really rapid, easy and straight forward 在简单的情况下,它确实是快速,简单而直接的

  • If you produced swig interface files once, you can wrap this C++ code to ANY of other 20+ languages (!!!). 如果您一次生成了swig接口文件,则可以将此C ++代码包装为其他20多种语言中的任何一种(!!!)。

  • One big concern about SWIG is a performance. SWIG的一大关注点是性能。 Since version 2.04 SWIG includes '-builtin' flag which makes SWIG even faster than other automated ways of wrapping. 从2.04版开始,SWIG包含“ -builtin”标志,这使得SWIG的速度比其他自动包装方式还快。 At least some benchmarks shows this. 至少一些基准测试表明了这一点。


When to USE SWIG? 何时使用SWIG?

So I concluded for myself two cases when the swig is good to use: 因此,我为自己总结了两种可以很好使用的情况:

2) If one needs to wrap C++ code for several languages . 2)如果需要包装几种语言的 C ++代码。 Or if potentially there could be a time when one needs to distribute the code for several languages. 或者,如果有可能某个时候需要分发几种语言的代码。 Using SWIG is reliable in this case. 在这种情况下,使用SWIG是可靠的。

1) If one needs to rapidly wrap just several functions from some C++ library for end use. 1)如果需要快速包装一些C ++库中的几个函数供最终使用。


Live experience 现场体验

Update : 更新
It is a year and a half passed as we did a conversion of our library by using SWIG. 过去了一年半,因为我们使用SWIG进行了图书馆的转换。

First, we made a python version. 首先,我们制作了一个python版本。 There were several moments when we experienced troubles with SWIG - it is true. 有好几次我们遇到SWIG的麻烦-的确如此。 But right now we expanded our library to Java and .NET. 但是现在我们将库扩展到Java和.NET。 So we have 3 languages with 1 SWIG. 因此,我们有1种SWIG的3种语言。 And I could say that SWIG rocks in terms of saving a LOT of time. 我可以说, SWIG节省了大量时间。

Update 2 : 更新2
It is two years as we use SWIG for this library. 我们将SWIG用于该库已经两年了。 SWIG is integrated into our build system. SWIG已集成到我们的构建系统中。 Recently we had major API change of C++ library. 最近,我们对C ++库进行了主要的API更改。 SWIG worked perfectly. SWIG运作良好。 The only thing we needed to do is to add several %rename to .i files so our CppCamelStyleFunctions() now looks_more_pythonish in python. 我们唯一需要做的就是将几个%rename添加到.i文件中,以便我们的CppCamelStyleFunctions()现在在python中使用looks_more_pythonish First I was concerned about some problems that could arise, but nothing went wrong. 首先,我担心会出现一些问题,但是没有出错。 It was amazing. 这是惊人的。 Just several edits and everything distributed in 3 languages. 只需几次编辑,所有内容均以3种语言发布。 Now I am confident that it was a good solution to use SWIG in our case. 现在,我相信在我们的案例中使用SWIG是一个很好的解决方案。

Update 3 : 更新3
It is 3+ years we use SWIG for our library. 我们将SWIG用于图书馆已超过3年。 Major change : python part was totally rewritten in pure python. 主要变化 :python部分完全用纯python重写。 The reason is that Python is used for the majority of applications of our library now. 原因是Python现在已用于我们库的大多数应用程序。 Even if the pure python version works slower than C++ wrapping, it is more convenient for users to work with pure python, not struggling with native libraries. 即使纯python版本比C ++包装慢,但用户使用纯python而不用苦于本机库也更方便。

SWIG is still used for .NET and Java versions. SWIG仍用于.NET和Java版本。

The Main question here "Would we use SWIG for python if we started the project from the beginning?". 这里的主要问题是:“如果我们从头开始启动项目,我们是否将SWIG用于python?”。 We would! 我们会! SWIG allowed us to rapidly distribute our product to many languages. SWIG使我们能够快速将产品分发为多种语言。 It worked for a period of time which gave us the opportunity for better understanding our users requirements. 它工作了一段时间,这使我们有机会更好地了解我们的用户需求。

SWIG generates (rather ugly) C or C++ code. SWIG生成(相当难看)C或C ++代码。 It is straightforward to use for simple functions (things that can be translated directly) and reasonably easy to use for more complex functions (such as functions with output parameters that need an extra translation step to represent in Python.) For more powerful interfacing you often need to write bits of C as part of the interface file. 它对于简单的函数(可以直接翻译的事物)简单易用,对于更复杂的函数(例如带有输出参数的函数,需要用额外的翻译步骤来用Python表示)则相当简单易用。需要将C的位写为接口文件的一部分。 For anything but simple use you will need to know about CPython and how it represents objects -- not hard, but something to keep in mind. 对于除简单使用之外的任何内容,您都需要了解CPython及其如何表示对象-不难,但要记住一些东西。

ctypes allows you to directly access C functions, structures and other data, and load arbitrary shared libraries. ctypes允许您直接访问C函数,结构和其他数据,并加载任意共享库。 You do not need to write any C for this, but you do need to understand how C works. 您不需要为此编写任何C,但是您确实需要了解C的工作原理。 It is, you could argue, the flip side of SWIG: it doesn't generate code and it doesn't require a compiler at runtime, but for anything but simple use it does require that you understand how things like C datatypes, casting, memory management and alignment work. 您可能会争辩说,它是SWIG的另一面:它不会生成代码,并且不需要在运行时进行编译器,但是对于简单使用而言,它确实需要您了解C数据类型,转换,内存管理和对齐工作。 You also need to manually or automatically translate C structs, unions and arrays into the equivalent ctypes datastructure, including the right memory layout. 您还需要手动或自动将C结构,联合和数组转换为等效的ctypes数据结构,包括正确的内存布局。

It is likely that in pure execution, SWIG is faster than ctypes -- because the management around the actual work is done in C at compiletime rather than in Python at runtime. 在纯执行中,SWIG可能比ctypes更快-因为围绕实际工作的管理是在C时在编译时完成的,而不是在Python时运行的。 However, unless you interface a lot of different C functions but each only a few times, it's unlikely the overhead will be really noticeable. 但是,除非您接口许多不同的C函数,但每次仅接口几次,否则开销实际上不会很明显。

In development time, ctypes has a much lower startup cost: you don't have to learn about interface files, you don't have to generate .c files and compile them, you don't have to check out and silence warnings. 在开发期间,ctypes的启动成本要低得多:您不必了解接口文件,不必生成.c文件并进行编译,也不必检出和静默警告。 You can just jump in and start using a single C function with minimal effort, then expand it to more. 您可以轻松投入并开始使用单个C函数,然后将其扩展为更多功能。 And you get to test and try things out directly in the Python interpreter. 您可以直接在Python解释器中进行测试并尝试尝试。 Wrapping lots of code is somewhat tedious, although there are attempts to make that simpler (like ctypes-configure.) 打包大量代码有些乏味,尽管有人尝试使代码简化(例如ctypes-configure)。

SWIG, on the other hand, can be used to generate wrappers for multiple languages (barring language-specific details that need filling in, like the custom C code I mentioned above.) When wrapping lots and lots of code that SWIG can handle with little help, the code generation can also be a lot simpler to set up than the ctypes equivalents. 另一方面,SWIG可用于为多种语言生成包装器(除非需要填写特定于语言的详细信息,例如我上面提到的自定义C代码。)当包装很多SWIG可以用很少的代码处理的代码时帮助,代码生成也可以比等效的ctypes简单得多。

CTypes is very cool and much easier than SWIG, but it has the drawback that poorly or malevolently-written python code can actually crash the python process. CTypes非常酷,比SWIG容易得多,但是它的缺点是编写不当或恶意编写的python代码实际上会使python进程崩溃。 You should also consider boost python. 您还应该考虑使用boost python。 IMHO it's actually easier than swig while giving you more control over the final python interface. 恕我直言,它实际上比Swig更容易,同时可以让您更好地控制最终的python接口。 If you are using C++ anyway, you also don't add any other languages to your mix. 如果仍在使用C ++,则也不会在混合中添加任何其他语言。

In my experience, ctypes does have a big disadvantage: when something goes wrong (and it invariably will for any complex interfaces), it's a hell to debug. 以我的经验,ctypes确实有一个很大的劣势:当出现问题时(对于任何复杂的接口它总是会出现问题),调试起来实在是太麻烦了。

The problem is that a big part of your stack is obscured by ctypes/ffi magic and there is no easy way to determine how did you get to a particular point and why parameter values are what they are.. 问题在于,ctypes / ffi魔术掩盖了堆栈的很大一部分,并且没有简单的方法来确定如何到达特定点以及为什么参数值就是它们。

You can also use Pyrex , which can act as glue between high-level Python code and low-level C code. 您还可以使用Pyrex ,它可以充当高级Python代码和低级C代码之间的粘合剂。 lxml is written in Pyrex, for instance. 例如,lxml用Pyrex编写。

I'm going to be contrarian and suggest that, if you can, you should write your extension library using the standard Python API . 我会相反地建议,如果可以的话,建议您使用标准Python API编写扩展库。 It's really well-integrated from both a C and Python perspective... if you have any experience with the Perl API, you will find it a very pleasant surprise. 从C和Python角度来看,它确实集成得很好……如果您有使用Perl API的经验,您会发现它非常令人惊喜。

Ctypes is nice too, but as others have said, it doesn't do C++. Ctypes也很不错,但是正如其他人所说,它不支持C ++。

How big is the library you're trying to wrap? 您要包装的图书馆有多大? How quickly does the codebase change? 代码库更改速度有多快? Any other maintenance issues? 还有其他维护问题吗? These will all probably affect the choice of the best way to write the Python bindings. 这些都可能会影响对编写Python绑定的最佳方式的选择。

ctypes is great, but does not handle C++ classes. ctypes很棒,但是不能处理C ++类。 I've also found ctypes is about 10% slower than a direct C binding, but that will highly depend on what you are calling. 我还发现ctypes比直接C绑定慢10%,但这在很大程度上取决于您所调用的内容。

If you are going to go with ctypes, definitely check out the Pyglet and Pyopengl projects, that have massive examples of ctype bindings. 如果要使用ctypes,请一定要查看Pyglet和Pyopengl项目,它们有大量ctype绑定示例。

Just wanted to add a few more considerations that I didn't see mentioned yet. 只是想补充一些我尚未提到的注意事项。 [EDIT: Ooops, didn't see Mike Steder's answer] [编辑:糟糕,没有看到Mike Steder的回答]

If you want to try using a non Cpython implementation (like PyPy, IronPython or Jython), then ctypes is about the only way to go. 如果您想尝试使用非Cpython实现(例如PyPy,IronPython或Jython),则ctypes是唯一可行的方法。 PyPy doesn't allow writing C-extensions, so that rules out pyrex/cython and Boost.python. PyPy不允许编写C扩展名,因此排除了pyrex / cython和Boost.python。 For the same reason, ctypes is the only mechanism that will work for IronPython and (eventually, once they get it all working) jython. 出于相同的原因,ctypes是唯一适用于IronPython和jython的机制(最终,一旦它们全部起作用)。

As someone else mentioned, no compilation is required. 正如其他人所提到的,不需要编译。 This means that if a new version of the .dll or .so comes out, you can just drop it in, and load that new version. 这意味着,如果出现新版本的.dll或.so,则可以将其放入并加载该新版本。 As long as the none of the interfaces changed, it's a drop in replacement. 只要这些接口都没有改变,替换就可以了。

Something to keep in mind is that SWIG targets only the CPython implementation. 要记住的一点是,SWIG仅针对CPython实现。 Since ctypes is also supported by the PyPy and IronPython implementations it may be worth writing your modules with ctypes for compatibility with the wider Python ecosystem. 由于PyPy和IronPython实现也支持ctypes,因此可能值得用ctypes编写模块以与更广泛的Python生态系统兼容。

I have found SWIG to be be a little bloated in its approach (in general, not just Python) and difficult to implement without having to cross the sore point of writing Python code with an explicit mindset to be SWIG friendly, rather than writing clean well-written Python code. 我发现SWIG的方法有些肿(通常不只是Python),并且难以实现,而不必以明确的心态跨越编写Python代码的痛点,以实现SWIG友好,而不是编写得井井有条。编写的Python代码。 It is, IMHO, a much more straightforward process to write C bindings to C++ (if using C++) and then use ctypes to interface to any C layer. 恕我直言,这是将C绑定写入C ++(如果使用C ++),然后使用ctypes连接到任何C层的更为简单的过程。

If the library you are interfacing to has a C interface as part of the library, another advantage of ctypes is that you don't have to compile a separate python-binding library to access third-party libraries. 如果您要连接的库具有C接口作为库的一部分,则ctypes的另一个优点是您不必编译单独的python绑定库即可访问第三方库。 This is particularly nice in formulating a pure-python solution that avoids cross-platform compilation issues (for those third-party libs offered on disparate platforms). 在制定避免跨平台编译问题的纯Python解决方案时(对于在不同平台上提供的第三方库),这特别好。 Having to embed compiled code into a package you wish to deploy on something like PyPi in a cross-platform friendly way is a pain; 您必须以跨平台友好的方式将编译后的代码嵌入到程序包中才能部署在PyPi之类的程序上,这很痛苦。 one of my most irritating points about Python packages using SWIG or underlying explicit C code is their general inavailability cross-platform. 关于使用SWIG或底层显式C代码的Python程序包,我最恼人的要点之一是它们通常无法跨平台使用。 So consider this if you are working with cross-platform available third party libraries and developing a python solution around them. 因此,如果您正在使用跨平台的第三方库并围绕它们开发python解决方案,请考虑一下。

As a real-world example, consider PyGTK. 作为真实示例,请考虑PyGTK。 This (I believe) uses SWIG to generate C code to interface to the GTK C calls. 这(我相信)使用SWIG生成C代码以与GTK C调用接口。 I used this for the briefest time only to find it a real pain to set up and use, with quirky odd errors if you didn't do things in the correct order on setup and just in general. 我在最短的时间内使用它,只是发现它设置和使用时确实很痛苦,如果您在安装时未按正确的顺序执行操作(通常),则会出现古怪的奇数错误。 It was such a frustrating experience, and when I looked at the interace definitions provided by GTK on the web I realized what a simple excercise it would be to write a translator of those interface to python ctypes interface. 这真是令人沮丧的经历,当我在网络上查看GTK提供的接口定义时,我意识到将这些接口的转换器翻译为python ctypes接口是一件简单的事情。 A project called PyGGI was born, and in ONE day I was able to rewrite PyGTK to be a much more functiona and useful product that matches cleanly to the GTK C-object-oriented interfaces. 一个名为PyGGI的项目诞生了,一天之内,我就能够重写PyGTK,使其成为功能更强大,更有用的产品,可以与GTK C面向对象的接口完全匹配。 And it required no compilation of C-code making it cross-platform friendly. 而且它不需要编译C代码即可使其跨平台友好。 (I was actually after interfacing to webkitgtk, which isn't so cross-platform). (我实际上是在与webkitgtk交互之后,但并不是跨平台的)。 I can also easily deploy PyGGI to any platform supporting GTK. 我还可以轻松地将PyGGI部署到任何支持GTK的平台。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM