动态加载两个libpython版本

动态加载两个libpython版本,python,c,dynamic,Python,C,Dynamic,我有一个同时嵌入python2和python3解释器的程序。libpython共享库由相应的命令dlopen()编辑,这些命令提供对解释器的访问,并且每个解释器维护自己的状态 如果用户只使用纯python模块或内置模块,这一切都很好。尝试加载C扩展(如termios)时,会抱怨“未定义的符号:PyExc_TypeError”。这是因为C扩展没有链接到libpython。Python上游不认为这是一个错误 为了解决这个问题,我可以将程序中libpython共享库的dlopen()调用更改为使用RT

我有一个同时嵌入python2和python3解释器的程序。libpython共享库由相应的命令
dlopen()
编辑,这些命令提供对解释器的访问,并且每个解释器维护自己的状态

如果用户只使用纯python模块或内置模块,这一切都很好。尝试加载C扩展(如termios)时,会抱怨“未定义的符号:PyExc_TypeError”。这是因为C扩展没有链接到libpython。Python上游不认为这是一个错误

为了解决这个问题,我可以将程序中libpython共享库的
dlopen()
调用更改为使用
RTLD\u GLOBAL
。然而,一旦我这样做,试图在程序的同一会话中同时使用python2和python3解释器就会导致它在调用
Py\u Initialize
的过程中对第二个被调用的解释器进行ABRT。只使用一个口译员就可以了


当C扩展无法与libpython链接,因此需要使用
RTLD\u GLOBAL
时,您知道如何让它工作吗?

对不起,这不会按您希望的方式工作。解决方案通常包括将每个扩展链接到版本化的libpython符号;或者可以有一个支持名称空间的链接器,这样就可以将每个库映射到不同的名称空间,而不是全局名称空间。不幸的是,这两个选项都不容易应用,因此您可能被困在多进程模型中。只需使用fork,每个版本的Python都有一个进程链接。那么,最困难的一点是如何共享任何数据,这导致您首先需要两个不同的Python解释器。也许,描述导致该问题的问题可能有助于找到更好的解决方案?

对不起,这不会按您希望的方式工作。解决方案通常包括将每个扩展链接到版本化的libpython符号;或者可以有一个支持名称空间的链接器,这样就可以将每个库映射到不同的名称空间,而不是全局名称空间。不幸的是,这两个选项都不容易应用,因此您可能被困在多进程模型中。只需使用fork,每个版本的Python都有一个进程链接。那么,最困难的一点是如何共享任何数据,这导致您首先需要两个不同的Python解释器。也许,描述导致该问题的问题可能有助于找到更好的解决方案?

该程序允许使用python解释器编写脚本。它以前只支持Python2,但最近获得了Python3的支持。这个想法并不是要强制一个或另一个选项,特别是因为已经存在使用Python2接口编写的脚本。我想可以更改它,以跟踪一个接口是否已加载,然后阻止另一个接口加载。这仍然提供了使用两个口译员进行构建的灵活性,但避免了整个崩溃问题。:)这似乎是一个简单的解决办法,尽管有点有限。更复杂的选项是将脚本接口与语言绑定分离,通过子流程运行该接口,然后让每个子流程链接到您喜欢的版本。它的效率不高,而且可能完全不实用,这取决于您当前的界面,但考虑到您现在可以打开它,它可能是可行的。该程序允许使用python解释器编写脚本。它以前只支持Python2,但最近获得了Python3的支持。这个想法并不是要强制一个或另一个选项,特别是因为已经存在使用Python2接口编写的脚本。我想可以更改它,以跟踪一个接口是否已加载,然后阻止另一个接口加载。这仍然提供了使用两个口译员进行构建的灵活性,但避免了整个崩溃问题。:)这似乎是一个简单的解决办法,尽管有点有限。更复杂的选项是将脚本接口与语言绑定分离,通过子流程运行该接口,然后让每个子流程链接到您喜欢的版本。它的效率不高,并且可能完全不实用,这取决于您当前的接口,但是考虑到您现在可以打开它,它可能是可行的。