是否可以拆分 SWIG 模块进行编译,但在链接时重新加入?
Posted
技术标签:
【中文标题】是否可以拆分 SWIG 模块进行编译,但在链接时重新加入?【英文标题】:Is it possible to split a SWIG module for compilation, but rejoin it when linking? 【发布时间】:2009-03-30 15:40:18 【问题描述】:大约两年前,当我第一次实现我们的 SWIG 绑定时,我遇到了这个问题。一旦我们暴露了大量代码,我们就达到了 SWIG 会输出 C++ 文件的地步,编译器无法处理它们。我可以解决这个问题的唯一方法是将接口拆分为多个模块并分别编译它们。
这有几个缺点:
• 每个模块都必须了解其他模块的依赖关系。我有一个脚本来生成处理这方面事情的接口文件,但它增加了额外的复杂性。
• 每个附加模块都会增加动态链接器在代码中加载所需的时间。我添加了一个导入所有子模块的 init.py 文件,这样代码被拆分的事实对用户来说是透明的,但始终可见的是加载时间长。
我目前正在审查我们的构建脚本/构建过程,我想看看我是否能找到比我现在更好的解决方案来解决这个问题。理想情况下,我会有一个包含所有包装代码的共享库。
有人知道我如何使用 SWIG 实现这一目标吗?我已经看到一些用 Ruby 为特定项目编写的自定义代码,其中的输出经过后处理以使其成为可能,但是当我查看 Python 包装器的可行性时,它看起来并不那么容易。
【问题讨论】:
【参考方案1】:我刚刚对 TCL 库进行了等效的 hack:我使用了几个 SWIG 模块,生成了几个 .cpp 文件,这些文件在几个 .o 文件中编译,但将它们全部编译在一个由单个 TCL “加载”加载的单个 .so 文件中"命令。
想法是创建一个***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 扩展。
【讨论】:
【参考方案2】:如果拆分得当,模块不一定需要与其他模块具有相同的依赖关系——这只是编译所必需的。如果您适当地分解事物,您可以拥有没有循环依赖关系的库。使用多个库的问题在于,默认情况下,SWIG 静态声明其运行时代码,因此,将对象从一个模块传递到另一个模块时出现问题。您需要启用 SWIG 运行时代码的共享版本。
来自文档(SWIG 网页文档链接已损坏):
运行时函数是私有的 每个 SWIG 生成的模块。那是, 声明了运行时函数 具有“静态”链接并且可见 仅限于定义的包装函数 在那个模块中。唯一的问题 这种方法是当超过 一个 SWIG 模块用于同一 应用程序,这些模块通常需要 共享类型信息。这是 对于 C++ 程序尤其如此 SWIG 必须收集和分享 关于继承的信息 跨模块的关系 边界。
查看您下载的文档中的该部分(第 16.2 节 SWIG 运行时代码),它将为您提供有关如何启用此功能的详细信息,以便在从一个模块传递到另一个模块时可以正确处理对象。
FWIW,我没有使用过 Python SWIG,但使用过 Tcl SWIG。
【讨论】:
我认为你有点忽略了这一点:我没有问题将东西从一个模块传递到另一个模块,一切都很好,注意“导入”语句。问题是我想将多个模块链接到一个共享库中以加快导入代码时的加载时间。 啊,很抱歉,没有解决方案可以加快速度。使用 Tcl,我们能够延迟加载模块,直到使用包机制需要它们。这确实有助于加快速度,但就简单地加快加载速度而言 - 没有骰子。以上是关于是否可以拆分 SWIG 模块进行编译,但在链接时重新加入?的主要内容,如果未能解决你的问题,请参考以下文章
为 Python 或 SWIG 模块创建编译 C-dll,如何继续?
Maven -- 分模块开发与设计 & 分模块开发示例(拆分POJO & 拆分DAO)
Openshift 无法加载 c++ bson 扩展/找不到模块('swig')