9

大约两年前,当我第一次实现我们的 SWIG 绑定时,我遇到了这个问题。一旦我们暴露了大量代码,我们就到了 SWIG 会输出 C++ 文件的地步,编译器无法处理它们。我可以解决这个问题的唯一方法是将接口拆分为多个模块并分别编译它们。

这有几个缺点:

• 每个模块都必须了解其他模块的依赖关系。我有一个脚本来生成处理这方面的接口文件,但它增加了额外的复杂性。

• 每个附加模块都会增加动态链接器加载代码所需的时间。我添加了一个导入所有子模块的init .py 文件,这样代码被拆分的事实对用户来说是透明的,但始终可见的是加载时间长。

我目前正在审查我们的构建脚本/构建过程,我想看看我是否能找到比我现在更好的解决方案来解决这个问题。理想情况下,我将拥有一个包含所有包装代码的共享库。

有谁知道我如何使用 SWIG 实现这一目标?我已经看到了一些用 Ruby 为特定项目编写的自定义代码,其中的输出经过后处理以使其成为可能,但是当我查看 Python 包装器的可行性时,它看起来并不那么容易。

4

2 回答 2

2

我刚刚对 TCL 库做了等效的 hack:我使用了几个 SWIG 模块,生成了几个 .cpp 文件,这些文件在几个 .o 文件中编译,但将它们全部编译到一个 .so 文件中,该文件由单个 TCL“加载”命令加载。

这个想法是创建一个顶级 swig 模块(Top),它调用所有子模块(Sub1 和 Sub2)的初始化函数:

%module Top
%header %{
  extern "C" {
    SWIGEXPORT int Sub1_Init(Tcl_Interp *);
    SWIGEXPORT int Sub2_Init(Tcl_Interp *);
  }
%}
%init %{
    if (Sub1_Init(interp) != TCL_OK) {return TCL_ERROR;}
    if (Sub2_Init(interp) != TCL_OK) {return TCL_ERROR;}
%}

子模块文件中没有什么特别之处。我最终得到了文件 Top.so,因此我使用命令“load ./Top.so”从 TCL 加载

我不知道python,但可能很相似。不过,您可能需要了解如何加载 python 扩展。

于 2017-01-11T13:40:45.343 回答
0

如果正确拆分,模块不一定需要与其他模块具有相同的依赖关系——这只是编译所必需的。如果你适当地分解事物,你可以拥有没有循环依赖的库。使用多个库的问题在于,默认情况下,SWIG 静态声明其运行时代码,因此,将对象从一个模块传递到另一个模块时出现问题。您需要启用 SWIG 运行时代码的共享版本。

从文档(SWIG 网页文档链接已损坏):

运行时函数对于每个 SWIG 生成的模块都是私有的。也就是说,运行时函数是用“静态”链接声明的,并且仅对该模块中定义的包装函数可见。这种方法的唯一问题是,当在同一个应用程序中使用多个 SWIG 模块时,这些模块通常需要共享类型信息。对于 SWIG 必须收集和共享有关跨模块边界的继承关系的信息的 C++ 程序尤其如此。

查看您下载的文档中的该部分(第 16.2 节 SWIG 运行时代码),它将为您提供有关如何启用此功能的详细信息,以便在从一个模块传递到另一个模块时可以正确处理对象。

FWIW,我没有使用过 Python SWIG,但做过 Tcl SWIG。

于 2009-03-30T16:59:19.493 回答