无法在 python 中导入自定义 DLL

Unable to import a custom DLL in python

我正在尝试使用 boost::python 将 C++ class 公开给 python,所以我正在经历 this tutorial。我用这个源代码创建了一个 visual studio .dll 项目:

#include <boost/python.hpp>
using namespace boost::python;

struct World
{
    void set(std::string msg) { this->msg = msg; }
    std::string greet() { return msg; }
    std::string msg;
};

BOOST_PYTHON_MODULE(hello)
{
    class_<World>("World")
        .def("greet", &World::greet)
        .def("set", &World::set)
    ;
}

我将它构建为 64 位 dll。教程的下一步说:

Here, we wrote a C++ class wrapper that exposes the member functions greet and set. Now, after building our module as a shared library, we may use our class World in Python. Here's a sample Python session:

>>> import hello
>>> planet = hello.World()
>>> planet.set('howdy')
>>> planet.greet()
'howdy'

但是,在同一目录中启动 python 并键入 import hello 后,我得到

>>> import hello
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'hello'
>>>

我已尝试将 'dll' 文件重命名为 hello.dll,并复制 每个 输出文件(dllexpilklibpdb) 到 %PYTHONPATH%\DLLs,但我仍然无法将模块导入 python。

很多谷歌搜索让我 this article 推荐我使用 ctypes 来导入 dll。这让我可以加载 dll,但我仍然无法调用 "World" class。例如:

>>> import ctypes
>>> mydll = ctypes.cdll.LoadLibrary("hello")
>>> mydll
<CDLL 'hello', handle 7fef40a0000 at 0x775ba8>
>>> hello = mydll.World()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python35\lib\ctypes\__init__.py", line 360, in __getatt
r__
    func = self.__getitem__(name)
  File "C:\Program Files\Python35\lib\ctypes\__init__.py", line 365, in __getite
m__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'World' not found
>>>

所以有几个问题:

  1. 是否可以使用 ctypes 在 python 中导入 dll 而无需 ?该教程似乎表明它是,但没有提供有关将 dll 放入 python.

  2. 的正确方法的详细信息
  3. 我需要哪些文件以及在哪里?似乎我只需要 python shell 工作目录中 visual studio 的 dll 文件,但这显然对我不起作用。

  4. 为什么我不能通过ctypes调用World

一些更重要的细节:我正在使用 windows 7 64 位,python 3.5.2 64 位,以及 Visual Studio 2015 和 Boost 1.61。

实际上我是在发布问题后不久才想出答案的。感谢 this blog post,我发现只需将 hello.dll 重命名为 hello.pyd 就足够了。通过更多的谷歌搜索,我 认为 ctypes 仅适用于 C DLL,不适用于 C++,并且 not with boost!。 boost::python 的要点是消除对 ctypes 的需求并使 DLL 与 python 兼容。所以回答我自己的所有问题:

  1. 是,但必须有 .pyd 扩展名。

  2. 您只需要已编译的 dll 文件和 boost_python_vc140...dll(可能会有所不同)。但是,正如我所说,dll 文件必须重命名。

  3. 因为 ctypes 不是加载 boost::python dll 的正确工具!