C++ - Boost - Using Boost.Python library on Windows to create a DLL

Communication between 2 different language isn't so easy.

It's often possible to find libraries to help us achieve this behaviour.

That's what we are going to see in this Boost.Python tutorial for Windows.

Let's get started.

First of all

We need to install Python 3 and Boost on your computer.

So in order to have the exact same software and libraries installed in the exact same locations, I suggest to follow the 2 following tutorials:

  1. Pythonhttps://www.badprog.com/python-3-installing-on-windows-10
  2. Boosthttps://www.badprog.com/c-boost-setting-up-on-windows-10

For Visual Studio 2017 and MSVC 141, install Python 3.7 and Boost 1.71.0 for MSVC 141.

For Visual Studio 2019 and MSVC 142, install Python 3.9 and Boost 1.77.0 for MSVC 142.

Creating a DLL with Visual Studio

Let's now create a new project:

From Visual Studio > File > New > Project... > Installed > Visual C++ > Windows Desktop > Dynamic-Link Library (DLL).

Then:

  • Name: badprog_lib
  • Location: C:\dev\c++\py\
  • Let unchecked the Create directory for solution option (don't need for this tutorial).

Click OK.

So you have now the following directory:

  • C:\dev\c++\py\badprog_lib\

With classic files generated by Visual Studio like:

  • C:\dev\c++\py\badprog_lib\badprog_lib.cpp
  • C:\dev\c++\py\badprog_lib\badprog_lib.sln
  • And so on.

Setting the Visual Studio project platform

First thing is now to change the project platform in the Configuration manager:

From Visual Studio > Select (right click mouse) the badprog_lib project > Properties... > On upper right click the Configuration Mananger... push button > Change Active solution platform from x86 to x64 > Close.

Then still in the badprog_lib Property Pages, at top center, change the Platform from Win32 to x64 (if not automatically updated).

So you have now:

  • Configuration: Debug
  • Platform: x64

Then click OK.

You can stay in Debug mode or change it to Release (it won't change anything for our tutorial).

Setting Visual Studio include paths for Boost and Python

First let's set the includes.

From Visual Studio > Select the badprog_lib.cpp file.

Then right click mouse > Properties... > Configuration Properties > C/C++ > General > Additioal Include Directories > Edit > Add the 2 following lines:

For Visual Studio 2017 (and MSVC 141) you need to install Python 3.7:

  • C:\soft\boost_1_71_0
  • C:\soft\python37\include

For Visual Studio 2019 (and MSVC 142) you need to install Python 3.9:

  • C:\soft\boost_1_77_0
  • C:\soft\python39\include
Then OK > Apply > OK.

Setting Visual Studio library paths for Boost and Python

We've now to set the libraries.

Same thing but with the linker:

From Visual Studio > Right click the badprog_lib project > Properties > Configuration Properties > Linker > General Additioal Library Directories > Edit > Add the 5 following lines:

For MSVC 141 (2017)

  • C:\soft\boost_1_71_0\lib64-msvc-14.1
  • C:\soft\python37\DLLs
  • C:\soft\python37\Lib
  • C:\soft\python37\libs
  • C:\soft\python37\tcl
For MSVC 142 (2019)
  • C:\soft\boost_1_77_0\lib64-msvc-14.2
  • C:\soft\python39\DLLs
  • C:\soft\python39\Lib
  • C:\soft\python39\libs
  • C:\soft\python39\tcl
  •  

Then OK > Apply > OK.

Let's code a bit

It's now time to code our Dinamic-Link Library (DLL) from Visual Studio.

In our badprog_lib.cpp file let's add the following code:

For MSVC 141 (2017) and Python 3.7

// badprog.com

#include "stdafx.h"
#include <boost/python.hpp>

// ----------------------------------------------------------------------------
// sayHello
// ----------------------------------------------------------------------------
char const* sayHello() {
  //
  return "Hello world from Badprog :D";
}

// ----------------------------------------------------------------------------
// BOOST_PYTHON_MODULE(badprog_lib)
// It creates the badprog_lib module to import from Python
// ----------------------------------------------------------------------------
BOOST_PYTHON_MODULE(badprog_lib) {
  //
  boost::python::def("welcome", sayHello);
}

 

For MSVC 142 (2019) and Python 3.9

// badprog.com

#include "pch.h"
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python.hpp>

// ----------------------------------------------------------------------------
// sayHello
// ----------------------------------------------------------------------------
char const* sayHello() {
  //
  return "Hello world from Badprog :D";
}

// ----------------------------------------------------------------------------
// BOOST_PYTHON_MODULE(badprog_lib)
// It creates the badprog_lib module to import from Python
// ----------------------------------------------------------------------------
BOOST_PYTHON_MODULE(badprog_lib) {
  //
  boost::python::def("welcome", sayHello);
}

 

Then from Visual Studio > Build > Build badprog_lib.

After the build, you should have these lines in your Visual Studio Build Output:

1>------ Build started: Project: badprog_lib, Configuration: Debug x64 ------

1>dllmain.cpp

1>   Creating library C:\dev\c++\py\badprog_lib\x64\Debug\badprog_lib.lib and object C:\dev\c++\py\badprog_lib\x64\Debug\badprog_lib.exp

1>badprog_lib.vcxproj -> C:\dev\c++\py\badprog_lib\x64\Debug\badprog_lib.dll

========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
 

If yes you can check that the following DLL has been created:

  • C:\dev\c++\py\badprog_lib\x64\Debug\badprog_lib.dll

This DLL will serve as API for our Python script.

Now take this DLL and move it to the following directory:

  • C:\dev\c++\py\badprog_lib\

So we've this file like this:

  • C:\dev\c++\py\badprog_lib\badprog_lib.dll

Rename the extension from .dll to .pyd.

You have now the following file:

  • C:\dev\c++\py\badprog_lib\badprog_lib.pyd

This extension does really matter because without it the Python script won't be able to import it.

We've now 2 options in order to get the code from the badprog_lib.pyd library.

  1. Directly by typing the code from the Python console, line by line
  2. Creating a Python file and call this file from any console (PowerShell for example)

Typing the code from the Python console

From the C:\dev\c++\py\badprog_lib\ directory, open a console.

Then type:

py

Your console will become a Python interpreter.

And you should see something like this appears:

PS C:\dev\c++\py\badprog_lib> py

Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.

If yes, good news, you are in the Python console.

Let's now import our library and type the following command:

import badprog_lib

If nothing has happened, then that's great.

Let's continue by calling our C++ code:

badprog_lib.welcome()

The welcoming message should appears:

'Hello world from Badprog :D'

So to sum up here what you should have typed and seen:

PS C:\dev\c++\py\badprog_lib> py

Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> import badprog_lib

>>> badprog_lib.welcome()

'Hello world from Badprog :D'

>>>
 

Creating a Python file and call it from a console

Let's create a file named badprog_script.py in the same directory, so we've the following:

  • C:\dev\c++\py\badprog_lib\badprog_script.py

In this file we have to type the following code, that is exactly the same as the previous command in the Python interpreter:

// badprog.com
import badprog_lib

print(badprog_lib.welcome())

 

And now from this directory, open any console (Git bash, PowerShell, Cmd, etc.) and type:

py badprog_script.py

The output result will be:

Hello world from Badprog :D

Conclusion

A lot of things to check and set.

But you are now able to build a shared library directly from Visual Studio, call the Boost.Python library from a C++ code and use it with Python.

Good job, you did it. cool

Comments

Comment: 

Hi.
Thanks for the helpful tips on your website. I tried to follow these steps using MSVS 2019, boost 1.70, Python 3.7. When I convert the dll to pyd and try to import it in the interpreter it returns "ImportError: DLL load failed: The specified module could not be found." When I leave the file as a dll it imports fine but when I try to call the function it responds with "AttributeError: module 'moduleTest' has no attribute 'greet'". Please note that maindll.cpp has a number of other lines inserted by default. I tried with and without removing those lines but same results.

Comment: 

Hello,

Yes it's a classic error.

I guess you shouldn't have the same name in your code that the one in the tutorial.

You MUST import the same module name as the one in your code.

Just have a look in your badprog_lib.cpp file, I think the following line:

  • BOOST_PYTHON_MODULE(badprog_lib)

may not be the same as the one you used.

Anyway, I suggest to follow the tutorials (the 2 tutorials for installing Boost and Python) and this one with the exact same name for directories and files.

And once you get exactly how it works, you can change it your way. cool

Comment: 

Thanks for the reply. I'm sure I followed the steps correctly. I created another file just incase but I got the same results. I guess I'll have to install the exact same releases of python and boost.python and try again sometime later. Ill post again with the results.

Comment: 

Hi. It finally worked. I used VS2019, Boost 1_71, Python 3.7 on Windows 10. Maybe that was all that was needed to be done but I used a bit of a different approach this time in that I chose to create an empty project. Then, before adding a cpp file I went into the properties by right clicking on the solution on solution viewer>Configuration Properties>Platform Toolset and changing it to Visual Studio 2017 (v141). On the same tab I changed Target Extension and Configuration Type to .dll(could possibly use .pyd here but didn't risk it) and Dynamic Library(.dll), respectively. Then, I added a new item .cpp file and followed the code and instructions except that I didnt include "stdafx.h".

Im curious if this approach would work with the latest versions of Python, Boost.Python, and msvc toolset v142 as choosing the template creation option didnt work and was full of extra code.

Comment: 

Dude your comment helped me so much I was stuck creating an exe, as for msvc 142 I managed to get it to work by building boost with msvc 142

Comment: 

Hello,

Very nice! cool
Happy that you succeeded.

Interesting question about Visual Studio 2019 (msvc-142).
Maybe in another tutorial. angel

Comment: 

Thanks for the help. Keep up the good work. Looking forward to more tutorials.

Comment: 

laugh

Comment: 

ImportError: DLL load failed: The specified module could not be found, I am getting, can you please help me out in resolving, I am using windows 64bit, python3.7.4

Comment: 

when I use this instruction it works very well for me.

PS C:\dev\c++\py\badprog_lib> py

Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> import badprog_lib

>>> badprog_lib.welcome()

'Hello world from Badprog :D'

>>>

--------------------------------------------------------

but when I create the .py file and place the following lines I get an error message (Traceback (most recent call last):
File "C: xxxxxxx.py", line 2, in <module>
import HolaMundo_d
ImportError: DLL load failed while importing badprog_lib: The specified module could not be found.)

import badprog_lib

print(badprog_lib.welcome())

Comment: 

This example is pretty useful to understand Boost-python library. Can you please provide another example that passes a numpy array from python to c++ (defined as a dll/pyd file)? When I pass a numpy array I always get a message the specified module could not be found!

Comment: 

Great instructions that have worked in the past for me. But now I just cant work it out! I get "ImportError: DLL load failed while importing badprog_lib". I *am* importing the correct module name.

Actually followed the first comment from boostNoob to the point. But it still fails with that error.

Any updates on why this could be the case. Thanks!

Comment: 

Found the solution myself. Add

#define BOOST_PYTHON_STATIC_LIB

as the first row in badprog_lib.cpp

Comment: 

Indeed Johan,

Thank you, it seems to work like that only with MSVC 142 (2019).

I updated the tutorial laugh

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.