I am trying to expose a C++ class to python with boost::python
, so I am going through this tutorial. I created a visual studio .dll
project, with this source code:
#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)
;
}
And I built it as a 64-bit dll. The next step in the tutorial says:
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'
However, after launching python in the same directory and typing import hello
I get
>>> import hello
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'hello'
>>>
I have tried renaming the 'dll' files to hello.dll
, and also copying every output file (dll
, exp
, ilk
, lib
, and pdb
) to %PYTHONPATH%\DLLs
, yet I am still unable to import the module into python.
Much googling brought me to this article recommending I use ctypes
to import the dll
. This lets me load the dll
, but I am still unable to call the "World" class. For example:
>>> 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
>>>
So a couple questions:
Is it possible to import a
dll
in python without using ctypes? The tutorial seems to indicate that it is, but doesn't provide very much detail about the right way to get the dll into python.Which files do I need and where? It seems like I should only need the
dll
file from visual studio in the working directory of my python shell, but this is clearly not working for me.Why can't I call
World
through ctypes?
Some more important details: I am using windows 7 64-bit, python 3.5.2 64-bit, and Visual Studio 2015 with Boost 1.61.
I actually just figured out the answer shortly after posting the question. Thanks to this blog post I found out that simply renaming the
hello.dll
tohello.pyd
was enough. From some more googling, I think thatctypes
is only for C DLLs, not C++, and not with boost!. The point ofboost::python
, is to remove the need for ctypes and make the DLL compatible with python. So to answer all of my own questions:Yes, but it must have a
.pyd
extension.You only need the compiled
dll
file and theboost_python_vc140...dll
(may vary). However, like I said, thedll
file must be renamed.Because ctypes is not the right tool for loading a
boost::python
dll!