如何从.so文件导入python模块?
Posted
技术标签:
【中文标题】如何从.so文件导入python模块?【英文标题】:How to import python module from .so file? 【发布时间】:2012-06-10 11:32:20 【问题描述】:[me@hostname python]$ cat hello_world.cc
#include <string>
#include <Python.h>
#include <boost/python.hpp>
namespace
std::string greet() return "Helloworld";
using namespace boost::python;
BOOST_PYTHON_MODULE(hello_world)
def("greet",greet);
[me@hostnmae python]$ g++ -c -fPIC hello_world.cc -I/path/to/boost/headers -I/path/to/python/headers -o hello_world.o
[me@hostname python]$ g++ -shared -Wl,-soname,libhello_world.so -o libhello_world.so hello_world.o
[me@hostname python]$ python
Python 2.7.1 (r271:86832, Jan 10 2011, 09:46:57)
[GCC 3.4.5 20051201 (Red Hat 3.4.5-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append('.')
>>> import hello_world
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named hello_world
>>>
我创建了如上所示的 .so 文件,但我无法在 python 中导入。我错过了什么?
【问题讨论】:
【参考方案1】:获取“hello_world.so”文件并创建名为“hello_world.py”的新python文件(在同一目录中)。 把下面的代码放进去.. .
def __bootstrap__():
global __bootstrap__, __loader__, __file__
import sys, pkg_resources, imp
__file__ = pkg_resources.resource_filename(__name__,'hello_world.so')
__loader__ = None; del __bootstrap__, __loader__
imp.load_dynamic(__name__,__file__)
__bootstrap__()
现在您可以将这个 hello_world 导入为:
>>> import hello_world
【讨论】:
是否应该将“_bootstrap_”重命名为“_bootstrap”?我花了很多时间试图找到它的文档,以为它是一个特殊的保留字,但我找不到任何东西。来自python.org/dev/peps/pep-0008/#naming-conventions:_double_leading_and_trailing_underscore_:存在于用户控制的命名空间中的“神奇”对象或属性。例如。 _init_ 、 _import_ 或 _file_ 。永远不要发明这样的名字;仅按文档说明使用。 我们可以复制,但你可以添加一些关于信息的细节。它是如何工作的。 我用模块 readline 试过这个。我碰巧安装了带有 apt-get 的 python 版本 #1 (2.7.12),它有 readline,另一个版本 #2 (2.7.11),只是扩展了,它没有。因此,我在 sys.path 中的一个目录中为版本 #2 添加了 readline.py,并在同一目录中添加了指向 /usr/lib/python2.7/lib-dynload/readline.x86_64-linux-gnu 的符号链接。所以从版本#1开始。我仍然得到错误。 这是唯一的解决方案吗?我没有看到任何 Cython 文档,所以感觉像是一种解决方法。【参考方案2】:必须叫hello_world.so
,而不是libhello_world.so
。
【讨论】:
谢谢。现在我得到ImportError: ./hello_world.so: undefined symbol: _ZNK12boost_1_47_06python7objects21py_function_impl_base9max_arityEv
@balki:你没有链接到 Boost.Python。
我链接了 boost_python,现在我得到了ImportError: libboost_python: cannot open shared object file: No such file or directory
。如果我导出LD_LIBRARY_PATH=/path/to/boost_python_lib
,它工作正常。如何在 cmdline 中指定?
LD_LIBRARY_PATH=/path/to/boost_python_lib python
很简单。如果可以的话,我建议您将boost_python_lib
符号链接到/usr/local/lib
,然后您就可以轻松获得它。您还可以通过将-Wl,-rpath=/path/to/boost_python_lib
传递给编译器(实际上由链接器处理)来硬编码.so
文件中的路径。以上是关于如何从.so文件导入python模块?的主要内容,如果未能解决你的问题,请参考以下文章