带有嵌入式Python解释器的.so-type插件:如何链接/加载libpython?

问题描述

我有以下设置:

----------------------------
|     C++ Application      |
----------------------------
              |
          dlopen()s
              |
              v
----------------------------          -------------------
| C++ Plugin with embedded |--links-->| libpython3.8.so |
|    Python interpreter    |          -------------------
----------------------------
              |
            runs
              |
              v
----------------------------
|       Python script      |
----------------------------
              |
           imports
              |
              v
----------------------------
|   Python C extension     |
|   module (e.g.,numpy)   |
----------------------------

没有任何进一步的措施,由于this SO question中详述的原因,即从Python脚本中导入Python C扩展模块失败,即Python扩展无法“看到” libpython中的符号。

按照上述问题的答案在C ++插件调用dlopen("libpython3.8.so",RTLD_LAZY | RTLD_GLOBAL)时,它可以工作。但是,在运行时将构建时动态链接(即指定-lpython3.8)和“手动” dlopen()调用混合在一起对我来说似乎不合适。

因此,我正在寻找更严格的解决方案。我的第一个想法是完全跳过编译时链接,并完全依靠dlopen()来加载libpython。另外一个好处是,通过在我的插件的配置中提供一个选项来指定libpython的路径,这将使用户可以选择Python安装。但是,该方法不起作用,因为即使使用RTLD_LAZYlibpython中的变量也必须在应用程序加载C ++插件时已经可以解决

反之亦然,也可能只希望依赖于构建时链接。据我了解,这将需要一个链接时选项,以指示以与libpythondlopen()相同的符号可见性来加载RTLD_GLOBAL。但是,我不知道有任何这样的选择,到目前为止还找不到。

我的问题是:

  • 除了在构建时链接libpython和在运行时dlopen()之外,您能想到任何更好或更严格的解决方案吗?如果一种方法允许通过插件配置(独立于libpython环境变量)来选择LD_LIBRARY_PATH,那将是一个额外的好处。
  • 如果您也无法想到更好的解决方案,那么将构建时链接dlopen()混合使用会带来什么风险?特别是,
    • 如果出于某种原因-dlopen()加载了另一个libpython版本而不是链接的版本,将会发生什么事情?
    • -lpython3.8dlopen("libpython3.8.so",...)在它们始终解析为同一库文件的意义上是否相等?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)