-->
This step-by-step walkthrough shows how to use the Visual Studio IDE to create your own dynamic link library (DLL) written in Microsoft C++ (MSVC). Then it shows how to use the DLL from another C++ app. DLLs (also known as shared libraries in UNIX-based operating systems) are one of the most useful kinds of Windows components. You can use them as a way to share code and resources, and to shrink the size of your apps. DLLs can even make it easier to service and extend your apps.
In this walkthrough, you'll create a DLL that implements some math functions. Then you'll create a console app that uses the functions from the DLL. You'll also get an introduction to some of the programming techniques and conventions used in Windows DLLs.
This walkthrough covers these tasks:
Aug 22, 2019 This step-by-step walkthrough shows how to use the Visual Studio IDE to create your own dynamic link library (DLL) written in Microsoft C (MSVC). Then it shows how to use the DLL from another C app. DLLs (also known as shared libraries in UNIX-based operating systems) are one of the most useful kinds of Windows components. Mar 15, 2007 Creating and Using a DLL in Dev-C - posted in Programming: well i think there is something wrong with Dev-C when creating a DLL. But i have created a DLL project that should create a messagebox that says Hello. I load the library from.
Create a DLL project in Visual Studio.
Add exported functions and variables to the DLL.
Create a console app project in Visual Studio.
Use the functions and variables imported from the DLL in the console app.
Run the completed app.
Like a statically linked library, a DLL exports variables, functions, and resources by name. A client app imports the names to use those variables, functions, and resources. Unlike a statically linked library, Windows connects the imports in your app to the exports in a DLL at load time or at run time, instead of connecting them at link time. Windows requires extra information that isn't part of the standard C++ compilation model to make these connections. The MSVC compiler implements some Microsoft-specific extensions to C++ to provide this extra information. We explain these extensions as we go.
This walkthrough creates two Visual Studio solutions; one that builds the DLL, and one that builds the client app. The DLL uses the C calling convention. It can be called from apps written in other programming languages, as long as the platform, calling conventions, and linking conventions match. The client app uses implicit linking, where Windows links the app to the DLL at load-time. This linking lets the app call the DLL-supplied functions just like the functions in a statically linked library.
This walkthrough doesn't cover some common situations. The code doesn't show the use of C++ DLLs by other programming languages. It doesn't show how to create a resource-only DLL, or how to use explicit linking to load DLLs at run-time rather than at load-time. Rest assured, you can use MSVC and Visual Studio to do all these things.
For links to more information about DLLs, see Create C/C++ DLLs in Visual Studio. For more information about implicit linking and explicit linking, see Determine which linking method to use. For information about creating C++ DLLs for use with programming languages that use C-language linkage conventions, see Exporting C++ functions for use in C-language executables. For information about how to create DLLs for use with .NET languages, see Calling DLL Functions from Visual Basic Applications.
C++ How To Use Dll
Prerequisites
- A computer that runs Microsoft Windows 7 or later versions. We recommend Windows 10 for the best development experience.
A copy of Visual Studio. For information on how to download and install Visual Studio, see Install Visual Studio. When you run the installer, make sure that the Desktop development with C++ workload is checked. Don't worry if you didn't install this workload when you installed Visual Studio. You can run the installer again and install it now.
- A copy of Visual Studio. For information on how to download and install Visual Studio 2015, see Install Visual Studio 2015. Use a Custom installation to install the C++ compiler and tools, since they're not installed by default.
An understanding of the basics of using the Visual Studio IDE. If you've used Windows desktop apps before, you can probably keep up. For an introduction, see Visual Studio IDE feature tour.
An understanding of enough of the fundamentals of the C++ language to follow along. Don't worry, we don't do anything too complicated.
Note
This walkthrough assumes you're using Visual Studio 2017 version 15.9 or later. Some earlier versions of Visual Studio 2017 had defects in the code templates, or used different user interface dialogs. To avoid problems, use the Visual Studio Installer to update Visual Studio 2017 to version 15.9 or later.
Create the DLL project
In this set of tasks, you create a project for your DLL, add code, and build it. To begin, start the Visual Studio IDE, and sign in if you need to. The instructions vary slightly depending on which version of Visual Studio you're using. Make sure you have the correct version selected in the control in the upper left of this page.
To create a DLL project in Visual Studio 2019
On the menu bar, choose File > New > Project to open the Create a New Project dialog box.
At the top of the dialog, set Language to C++, set Platform to Windows, and set Project type to Library.
From the filtered list of project types, select Dynamic-link Library (DLL), and then choose Next.
In the Configure your new project page, enter MathLibrary in the Project name box to specify a name for the project. Leave the default Location and Solution name values. Set Solution to Create new solution. Uncheck Place solution and project in the same directory if it's checked.
Choose the Create button to create the project.
When the solution is created, you can see the generated project and source files in the Solution Explorer window in Visual Studio.
To create a DLL project in Visual Studio 2017
On the menu bar, choose File > New > Project to open the New Project dialog box.
In the left pane of the New Project dialog box, select Installed > Visual C++ > Windows Desktop. In the center pane, select Dynamic-Link Library (DLL). Enter MathLibrary in the Name box to specify a name for the project. Leave the default Location and Solution name values. Set Solution to Create new solution. Check Create directory for solution if it's unchecked.
Choose the OK button to create the project.
When the solution is created, you can see the generated project and source files in the Solution Explorer window in Visual Studio.
To create a DLL project in Visual Studio 2015 and older versions
On the menu bar, choose File > New > Project.
In the left pane of the New Project dialog box, expand Installed > Templates, and select Visual C++, and then in the center pane, select Win32 Console Application. Enter MathLibrary in the Name edit box to specify a name for the project. Leave the default Location and Solution name values. Set Solution to Create new solution. Check Create directory for solution if it's unchecked.
Choose the OK button to dismiss the New Project dialog and start the Win32 Application Wizard.
Choose the Next button. On the Application Settings page, under Application type, select DLL.
Choose the Finish button to create the project.
When the wizard completes the solution, you can see the generated project and source files in the Solution Explorer window in Visual Studio.
Right now, this DLL doesn't do very much. Next, you'll create a header file to declare the functions your DLL exports, and then add the function definitions to the DLL to make it more useful.
To add a header file to the DLL
To create a header file for your functions, on the menu bar, choose Project > Add New Item.
In the Add New Item dialog box, in the left pane, select Visual C++. In the center pane, select Header File (.h). Specify MathLibrary.h as the name for the header file.
Choose the Add button to generate a blank header file, which is displayed in a new editor window.
Replace the contents of the header file with this code:
This header file declares some functions to produce a generalized Fibonacci sequence, given two initial values. A call to fibonacci_init(1, 1)
generates the familiar Fibonacci number sequence.
Notice the preprocessor statements at the top of the file. The new project template for a DLL project adds PROJECTNAME_EXPORTS to the defined preprocessor macros. In this example, Visual Studio defines MATHLIBRARY_EXPORTS when your MathLibrary DLL project is built.
When the MATHLIBRARY_EXPORTS macro is defined, the MATHLIBRARY_API macro sets the __declspec(dllexport)
modifier on the function declarations. This modifier tells the compiler and linker to export a function or variable from the DLL for use by other applications. When MATHLIBRARY_EXPORTS is undefined, for example, when the header file is included by a client application, MATHLIBRARY_API applies the __declspec(dllimport)
modifier to the declarations. This modifier optimizes the import of the function or variable in an application. For more information, see dllexport, dllimport.
To add an implementation to the DLL
In Solution Explorer, right-click on the Source Files node and choose Add > New Item. Create a new .cpp file called MathLibrary.cpp, in the same way that you added a new header file in the previous step.
In the editor window, select the tab for MathLibrary.cpp if it's already open. If not, in Solution Explorer, double-click MathLibrary.cpp in the Source Files folder of the MathLibrary project to open it.
In the editor, replace the contents of the MathLibrary.cpp file with the following code:
In the editor window, select the tab for MathLibrary.cpp if it's already open. If not, in Solution Explorer, double-click MathLibrary.cpp in the Source Files folder of the MathLibrary project to open it.
In the editor, replace the contents of the MathLibrary.cpp file with the following code:
To verify that everything works so far, compile the dynamic link library. To compile, choose Build > Build Solution on the menu bar. The DLL and related compiler output are placed in a folder called Debug directly below the solution folder. If you create a Release build, the output is placed in a folder called Release. The output should look something like this:
Congratulations, you've created a DLL using Visual Studio! Next, you'll create a client app that uses the functions exported by the DLL.
Create a client app that uses the DLL
When you create a DLL, think about how client apps may use it. To call the functions or access the data exported by a DLL, client source code must have the declarations available at compile time. At link time, the linker requires information to resolve the function calls or data accesses. A DLL supplies this information in an import library, a file that contains information about how to find the functions and data, instead of the actual code. And at run time, the DLL must be available to the client, in a location that the operating system can find.
Whether it's your own or from a third-party, your client app project needs several pieces of information to use a DLL. It needs to find the headers that declare the DLL exports, the import libraries for the linker, and the DLL itself. One solution is to copy all of these files into your client project. For third-party DLLs that are unlikely to change while your client is in development, this method may be the best way to use them. However, when you also build the DLL, it's better to avoid duplication. If you make a local copy of DLL files that are under development, you may accidentally change a header file in one copy but not the other, or use an out-of-date library.
To avoid out-of-sync code, we recommend you set the include path in your client project to include the DLL header files directly from your DLL project. Also, set the library path in your client project to include the DLL import libraries from the DLL project. And finally, copy the built DLL from the DLL project into your client build output directory. This step allows your client app to use the same DLL code you build.
To create a client app in Visual Studio
On the menu bar, choose File > New > Project to open the Create a new project dialog box.
At the top of the dialog, set Language to C++, set Platform to Windows, and set Project type to Console.
From the filtered list of project types, choose Console App then choose Next.
In the Configure your new project page, enter MathClient in the Project name box to specify a name for the project. Leave the default Location and Solution name values. Set Solution to Create new solution. Uncheck Place solution and project in the same directory if it's checked.
Choose the Create button to create the client project.
A minimal console application project is created for you. The name for the main source file is the same as the project name that you entered earlier. In this example, it's named MathClient.cpp. You can build it, but it doesn't use your DLL yet.
To create a client app in Visual Studio 2017
To create a C++ app that uses the DLL that you created, on the menu bar, choose File > New > Project.
In the left pane of the New Project dialog, select Windows Desktop under Installed > Visual C++. In the center pane, select Windows Console Application. Specify the name for the project, MathClient, in the Name edit box. Leave the default Location and Solution name values. Set Solution to Create new solution. Check Create directory for solution if it's unchecked.
Choose OK to create the client app project.
A minimal console application project is created for you. The name for the main source file is the same as the project name that you entered earlier. In this example, it's named MathClient.cpp. You can build it, but it doesn't use your DLL yet.
To create a client app in Visual Studio 2015
To create a C++ app that uses the DLL that you created, on the menu bar, choose File > New > Project.
In the left pane of the New Project dialog, select Win32 under Installed > Templates > Visual C++. In the center pane, select Win32 Console Application. Specify the name for the project, MathClient, in the Name edit box. Leave the default Location and Solution name values. Set Solution to Create new solution. Check Create directory for solution if it's unchecked.
Choose the OK button to dismiss the New Project dialog and start the Win32 Application Wizard. On the Overview page of the Win32 Application Wizard dialog box, choose the Next button.
On the Application Settings page, under Application type, select Console application if it isn't already selected.
Choose the Finish button to create the project.
When the wizard finishes, a minimal console application project is created for you. The name for the main source file is the same as the project name that you entered earlier. In this example, it's named MathClient.cpp. You can build it, but it doesn't use your DLL yet.
Next, to call the MathLibrary functions in your source code, your project must include the MathLibrary.h file. You could copy this header file into your client app project, then add it to the project as an existing item. This method can be a good choice for third-party libraries. However, if you're working on the code for your DLL and your client at the same time, the header files could get out of sync. To avoid this issue, set the Additional Include Directories path in your project to include the path to the original header.
To add the DLL header to your include path
Right-click on the MathClient node in Solution Explorer to open the Property Pages dialog.
In the Configuration drop-down box, select All Configurations if it's not already selected.
In the left pane, select Configuration Properties > C/C++ > General.
In the property pane, select the drop-down control next to the Additional Include Directories edit box, and then choose Edit.
Double-click in the top pane of the Additional Include Directories dialog box to enable an edit control. Or, choose the folder icon to create a new entry.
In the edit control, specify the path to the location of the MathLibrary.h header file. You can choose the ellipsis (...) control to browse to the correct folder.
You can also enter a relative path from your client source files to the folder that contains the DLL header files. If you followed the directions to put your client project in a separate solution from the DLL, the relative path should look like this:
....MathLibraryMathLibrary
If your DLL and client projects are in the same solution, the relative path might look like this:
..MathLibrary
When the DLL and client projects are in other folders, adjust the relative path to match. Or, use the ellipsis control to browse for the folder.
After you've entered the path to the header file in the Additional Include Directories dialog box, choose the OK button. In the Property Pages dialog box, choose the OK button to save your changes.
You can now include the MathLibrary.h file and use the functions it declares in your client application. Replace the contents of MathClient.cpp by using this code:
This code can be compiled, but not linked. If you build the client app now, the error list shows several LNK2019 errors. That's because your project is missing some information: You haven't specified that your project has a dependency on the MathLibrary.lib library yet. And, you haven't told the linker how to find the MathLibrary.lib file.
To fix this issue, you could copy the library file directly into your client app project. The linker would find and use it automatically. However, if both the library and the client app are under development, that might lead to changes in one copy that aren't shown in the other. To avoid this issue, you can set the Additional Dependencies property to tell the build system that your project depends on MathLibrary.lib. And, you can set an Additional Library Directories path in your project to include the path to the original library when you link.
To add the DLL import library to your project
How To Create Dll File In Dev C Pdf
Right-click on the MathClient node in Solution Explorer and choose Properties to open the Property Pages dialog.
In the Configuration drop-down box, select All Configurations if it's not already selected. It ensures that any property changes apply to both Debug and Release builds.
In the left pane, select Configuration Properties > Linker > Input. In the property pane, select the drop-down control next to the Additional Dependencies edit box, and then choose Edit.
In the Additional Dependencies dialog, add MathLibrary.lib to the list in the top edit control.
Choose OK to go back to the Property Pages dialog box.
In the left pane, select Configuration Properties > Linker > General. In the property pane, select the drop-down control next to the Additional Library Directories edit box, and then choose Edit.
Double-click in the top pane of the Additional Library Directories dialog box to enable an edit control. In the edit control, specify the path to the location of the MathLibrary.lib file. By default, it's in a folder called Debug directly under the DLL solution folder. If you create a release build, the file is placed in a folder called Release. You can use the
$(IntDir)
macro so that the linker can find your DLL, no matter which kind of build you create. If you followed the directions to put your client project in a separate solution from the DLL project, the relative path should look like this:....MathLibrary$(IntDir)
If your DLL and client projects are in other locations, adjust the relative path to match.
Once you've entered the path to the library file in the Additional Library Directories dialog box, choose the OK button to go back to the Property Pages dialog box. Choose OK to save the property changes.
Your client app can now compile and link successfully, but it still doesn't have everything it needs to run. When the operating system loads your app, it looks for the MathLibrary DLL. If it can't find the DLL in certain system directories, the environment path, or the local app directory, the load fails. Depending on the operating system, you'll see an error message like this:
One way to avoid this issue is to copy the DLL to the directory that contains your client executable as part of the build process. You can add a Post-Build Event to your project, to add a command that copies the DLL to your build output directory. The command specified here copies the DLL only if it's missing or has changed. It uses macros to copy to and from the Debug or Release locations, based on your build configuration.
To copy the DLL in a post-build event
Right-click on the MathClient node in Solution Explorer and choose Properties to open the Property Pages dialog.
In the Configuration drop-down box, select All Configurations if it isn't already selected.
In the left pane, select Configuration Properties > Build Events > Post-Build Event.
In the property pane, select the edit control in the Command Line field. If you followed the directions to put your client project in a separate solution from the DLL project, then enter this command:
xcopy /y /d '....MathLibrary$(IntDir)MathLibrary.dll' '$(OutDir)'
If your DLL and client projects are in other directories, change the relative path to the DLL to match.
Choose the OK button to save your changes to the project properties.
Now your client app has everything it needs to build and run. Build the application by choosing Build > Build Solution on the menu bar. The Output window in Visual Studio should have something like the following example depending on your version of Visual Studio:
Congratulations, you've created an application that calls functions in your DLL. Now run your application to see what it does. On the menu bar, choose Debug > Start Without Debugging. Visual Studio opens a command window for the program to run in. The last part of the output should look like:
Press any key to dismiss the command window.
Now that you've created a DLL and a client application, you can experiment. Try setting breakpoints in the code of the client app, and run the app in the debugger. See what happens when you step into a library call. Add other functions to the library, or write another client app that uses your DLL.
When you deploy your app, you must also deploy the DLLs it uses. The simplest way to make the DLLs that you build, or that you include from third parties, available is to put them in the same directory as your app. It's known as app-local deployment. For more information about deployment, see Deployment in Visual C++.
See also
-->Modules written in C++ (or C) are commonly used to extend the capabilities of a Python interpreter as well as to enable access to low-level operating system capabilities. There are three primary types of modules:
- Accelerator modules: because Python is an interpreted language, certain pieces of code can be written in C++ for higher performance.
- Wrapper modules: expose existing C/C++ interfaces to Python code or expose a more 'Pythonic' API that's easy to use from Python.
- Low-level system access modules: created to access lower-level features of the CPython runtime, the operating system, or the underlying hardware.
This article walks through building a C++ extension module for CPython that computes a hyperbolic tangent and calls it from Python code. The routine is implemented first in Python to demonstrate the relative performance gain of implementing the same routine in C++.
This article also demonstrates two ways to make the C++ available to Python:
Dll File Mac
- The standard CPython extensions as described in the Python documentation
- PyBind11, which is recommended for C++ 11 because of its simplicity.
A comparison between these and other means is found under alternative approaches at the end of this article.
The completed sample from this walkthrough can be found on python-samples-vs-cpp-extension (GitHub).
Prerequisites
Visual Studio 2017 or later with both the Desktop Development with C++ and Python Development workloads installed with default options.
In the Python Development workload, also select the box on the right for Python native development tools. This option sets up most of the configuration described in this article. (This option also includes the C++ workload automatically.)
Tip
Installing the Data science and analytical applications workload also includes Python and the Python native development tools option by default.
For more information, see Install Python support for Visual Studio, including using other versions of Visual Studio. If you install Python separately, be sure to select Download debugging symbols and Download debug binaries under Advanced Options in the installer. This option ensures that you have the necessary debug libraries available if you choose to do a debug build.
Create the Python application
Create a new Python project in Visual Studio by selecting File > New > Project. Search for 'Python', select the Python Application template, give it a suitable name and location, and select OK.
Working with C++ requires that you use a 32-bit Python interpreter (Python 3.6 or above recommended). In the Solution Explorer window of Visual Studio, expand the project node, then expand the Python Environments node. If you don't see a 32-bit environment as the default (either in bold, or labeled with global default), then follow the instructions on Select a Python environment for a project. If you don't have a 32-bit interpreter installed, see Install Python interpreters.
In the project's .py file, paste the following code that benchmarks the computation of a hyperbolic tangent (implemented without using the math library for easier comparison). Feel free to enter the code manually to experience some of the Python editing features.
Run the program using Debug > Start without Debugging (Ctrl+F5) to see the results. You can adjust the
COUNT
variable to change how long the benchmark takes to run. For the purposes of this walkthrough, set the count so that the benchmark take around two seconds.
Tip
When running benchmarks, always use Debug > Start without Debugging to avoid the overhead incurred when running code within the Visual Studio debugger.
Create the core C++ projects
Follow the instructions in this section to create two identical C++ projects named 'superfastcode' and 'superfastcode2'. Later you'll use different means in each project to expose the C++ code to Python.
Make sure the
PYTHONHOME
environment variable is set to the Python interpreter you want to use. The C++ projects in Visual Studio rely on this variable to locate files such as python.h, which are used when creating a Python extension.Right-click the solution in Solution Explorer and select Add > New Project. A Visual Studio solution can contain both Python and C++ projects together (which is one of the advantages of using Visual Studio for Python).
Search on 'C++', select Empty project, specify the name 'superfastcode' ('superfastcode2' for the second project), and select OK.
Tip
With the Python native development tools installed in Visual Studio, you can start with the Python Extension Module template instead, which has much of what's described below already in place. For this walkthrough, though, starting with an empty project demonstrates building the extension module step by step. Once you understand the process, the template saves you time when writing your own extensions.
Create a C++ file in the new project by right-clicking the Source Files node, then select Add > New Item, select C++ File, name it
module.cpp
, and select OK.Important
A file with the .cpp extension is necessary to turn on the C++ property pages in the steps that follow.
Right-click the C++ project in Solution Explorer, select Properties.
At the top of the Property Pages dialog that appears, set Configuration to All Configurations and Platform to Win32.
Set the specific properties as described in the following table, then select OK.
Tab Property Value General General > Target Name Specify the name of the module as you want to refer to it from Python in from...import
statements. You use this same name in the C++ when defining the module for Python. If you want to use the name of the project as the module name, leave the default value of $(ProjectName).General > Target Extension .pyd Project Defaults > Configuration Type Dynamic Library (.dll) C/C++ > General Additional Include Directories Add the Python include folder as appropriate for your installation, for example, c:Python36include
.C/C++ > Preprocessor Preprocessor Definitions CPython only: add Py_LIMITED_API;
to the beginning of the string (including the semicolon). This definition restricts some of the functions you can call from Python and makes the code more portable between different versions of Python. If you're working with PyBind11, don't add this definition, otherwise you'll see build errors.C/C++ > Code Generation Runtime Library Multi-threaded DLL (/MD) (see Warning below) Linker > General Additional Library Directories Add the Python libs folder containing .lib files as appropriate for your installation, for example, c:Python36libs
. (Be sure to point to the libs folder that contains .lib files, and not the Lib folder that contains .py files.)Tip
If you don't see the C/C++ tab in the project properties, it's because the project doesn't contain any files that it identifies as C/C++ source files. This condition can occur if you create a source file without a .c or .cpp extension. For example, if you accidentally entered
module.coo
instead ofmodule.cpp
in the new item dialog earlier, then Visual Studio creates the file but doesn't set the file type to 'C/C+ Code,' which is what activates the C/C++ properties tab. Such misidentification remains the case even if you rename the file with.cpp
. To set the file type properly, right-click the file in Solution Explorer, select Properties, then set File Type to C/C++ Code.Warning
Always set the C/C++ > Code Generation > Runtime Library option to Multi-threaded DLL (/MD), even for a debug configuration, because this setting is what the non-debug Python binaries are built with. With CPython, if you happen to set the Multi-threaded Debug DLL (/MDd) option, building a Debug configuration produces error C1189: Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, and Py_REF_DEBUG. Furthermore, if you remove
Py_LIMITED_API
(which is required with CPython, but not PyBind11) to avoid the build error, Python crashes when attempting to import the module. (The crash happens within the DLL's call toPyModule_Create
as described later, with the output message of Fatal Python error: PyThreadState_Get: no current thread.)The /MDd option is used to build the Python debug binaries (such as python_d.exe), but selecting it for an extension DLL still causes the build error with
Py_LIMITED_API
.Right-click the C++ project and select Build to test your configurations (both Debug and Release). The .pyd files are located in the solution folder under Debug and Release, not the C++ project folder itself.
Add the following code to the C++ project's module.cpp file:
Build the C++ project again to confirm that your code is correct.
If you haven't already done so, repeat the steps above to create a second project named 'superfastcode2' with identical contents.
Convert the C++ projects to extensions for Python
To make the C++ DLL into an extension for Python, you first modify the exported methods to interact with Python types. You then add a function that exports the module, along with definitions of the module's methods.
The sections that follow explain how to perform these steps using both the CPython extensions and PyBind11.
CPython extensions
For background on what's shown in this section for Python 3.x, refer to the Python/C API Reference Manual and especially Module Objects on python.org (remember to select your version of Python from the drop-down control on the upper right to view the correct documentation).
If you're working with Python 2.7, refer instead to Extending Python 2.7 with C or C++ and Porting Extension Modules to Python 3 (python.org).
At the top of module.cpp, include Python.h:
Modify the
tanh_impl
method to accept and return Python types (aPyOjbect*
, that is):Add a structure that defines how the C++
tanh_impl
function is presented to Python:Add a structure that defines the module as you want to refer to it in your Python code, specifically when using the
from...import
statement. (Make this match the value in the project properties under Configuration Properties > General > Target Name.) In the following example, the 'superfastcode' module name means you can usefrom superfastcode import fast_tanh
in Python, becausefast_tanh
is defined withinsuperfastcode_methods
. (Filenames internal to the C++ project, like module.cpp, are inconsequential.)Add a method that Python calls when it loads the module, which must be named
PyInit_<module-name>
, where <module-name> exactly matches the C++ project's General > Target Name property (that is, it matches the filename of the .pyd built by the project).Set the target configuration to Release and build the C++ project again to verify your code. If you encounter errors, see the Troubleshooting section below.
PyBind11
If you completed the steps in the previous section, you certainly noticed that you used lots of boilerplate code to create the necessary module structures for the C++ code. PyBind11 simplifies the process through macros in a C++ header file that accomplish the same result with much less code. For background on what's shown in this section, see PyBind11 basics (github.com).
Install PyBind11 using pip:
pip install pybind11
orpy -m pip install pybind11
.At the top of module.cpp, include pybind11.h:
At the bottom of module.cpp, use the
PYBIND11_MODULE
macro to define the entrypoint to the C++ function:Set the target configuration to Release and build the C++ project to verify your code. If you encounter errors, see the next section on troubleshooting.
Troubleshooting
The C++ module may fail to compile for the following reasons:
Unable to locate Python.h (E1696: cannot open source file 'Python.h' and/or C1083: Cannot open include file: 'Python.h': No such file or directory): verify that the path in C/C++ > General > Additional Include Directories in the project properties points to your Python installation's include folder. See step 6 under Create the core C++ project.
Unable to locate Python libraries: verify that the path in Linker > General > Additional Library Directories in the project properties points to your Python installation's libs folder. See step 6 under Create the core C++ project.
Linker errors related to target architecture: change the C++ target's project architecture to match that of your Python installation. For example, if you're targeting x64 with the C++ project but your Python installation is x86, change the C++ project to target x86.
Test the code and compare the results
Now that you have the DLLs structured as Python extensions, you can refer to them from the Python project, import the modules, and use their methods.
Make the DLL available to Python
There are two ways to make the DLL available to Python.
The first method works if the Python project and the C++ project are in the same solution. Go to Solution Explorer, right-click the References node in your Python project, and then select Add Reference. In the dialog that appears, select the Projects tab, select both the superfastcode and superfastcode2 projects, and then select OK.
The alternate method, described in the following steps, installs the module in the global Python environment, making it available to other Python projects as well. (Doing so typically requires that you refresh the IntelliSense completion database for that environment in Visual Studio 2017 version 15.5 and earlier. Refreshing is also necessary when removing the module from the environment.)
If you're using Visual Studio 2017 or later, run the Visual Studio installer, select Modify, select Individual Components > Compilers, build tools, and runtimes > Visual C++ 2015.3 v140 toolset. This step is necessary because Python (for Windows) is itself built with Visual Studio 2015 (version 14.0) and expects that those tools are available when building an extension through the method described here. (Note that you may need to install a 32-bit version of Python and target the DLL to Win32 and not x64.)
Create a file named setup.py in the C++ project by right-clicking the project and selecting Add > New Item. Then select C++ File (.cpp), name the file
setup.py
, and select OK (naming the file with the .py extension makes Visual Studio recognize it as Python despite using the C++ file template). When the file appears in the editor, paste the following code into it as appropriate to the extension method:CPython extensions (superfastcode project):
See Building C and C++ extensions (python.org) for documentation on this script.
PyBind11 (superfastcode2 project):
The setup.py code instructs Python to build the extension using the Visual Studio 2015 C++ toolset when used from the command line. Open an elevated command prompt, navigate to the folder containing the C++ project (that is, the folder that contains setup.py), and enter the following command:
or:
Call the DLL from Python
How To Create Dll File In Dev C Download
After you've made the DLL available to Python as described in the previous section, you can now call the superfastcode.fast_tanh
and superfastcode2.fast_tanh2
functions from Python code and compare their performance to the Python implementation:
Add the following lines in your .py file to call methods exported from the DLLs and display their outputs:
Run the Python program (Debug > Start without Debugging or Ctrl+F5) and observe that the C++ routines run approximately five to twenty times faster than the Python implementation. Typical output appears as follows:
If the Start Without Debugging command is disabled, right-click the Python project in Solution Explorer and select Set as Startup Project.
Try increasing the
COUNT
variable so that the differences are more pronounced. A Debug build of the C++ module also runs slower than a Release build because the Debug build is less optimized and contains various error checks. Feel free to switch between those configurations for comparison.
Note
How To Create Dll File In C++
In the output, you can see that the PyBind11 extension isn't as fast as the CPython extension, though it's still significantly faster than the straight Python implementation. The difference is due to a small amount of per-call overhead that PyBind11 introduces in order to make its C++ interface dramatically simpler. This per-call difference is actually quite negligible: because the test code calls the extension functions 500,000 times, the results you see here greatly amplify that overhead! Typically, a C++ function does much more work than the trivial fast_tanh[2]
methods used here, in which case the overhead is unimportant. However, if you're implementing methods that might be called thousands of times per second, using the CPython approach can result in better performance than PyBind11.
Debug the C++ code
Dev C++ Create Dll
Visual Studio supports debugging Python and C++ code together. This section walks through the process using the superfastcode project; the steps are the same for the superfastcode2 project.
Right-click the Python project in Solution Explorer, select Properties, select the Debug tab, and then select the Debug > Enable native code debugging option.
Tip
When you enable native code debugging, the Python output window may disappear immediately when the program has completed without giving you the usual Press any key to continue pause. To force a pause, add the
-i
option to the Run > Interpreter Arguments field on the Debug tab when you enable native code debugging. This argument puts the Python interpreter into interactive mode after the code finishes, at which point it waits for you to press Ctrl+Z > Enter to exit. (Alternately, if you don't mind modifying your Python code, you can addimport os
andos.system('pause')
statements at the end of your program. This code duplicates the original pause prompt.)Select File > Save to save the property changes.
Set the build configuration to Debug in the Visual Studio toolbar.
Because code generally takes longer to run in the debugger, you may want to change the
COUNT
variable in your .py file to a value that's about five times smaller (for example, change it from500000
to100000
).In your C++ code, set a breakpoint on the first line of the
tanh_impl
method, then start the debugger (F5 or Debug > Start Debugging). The debugger stops when that code is called. If the breakpoint is not hit, check that the configuration is set to Debug and that you've saved the project (which does not happen automatically when starting the debugger).At this point you can step through the C++ code, examine variables, and so on. These features are detailed in Debug C++ and Python together.
Alternative approaches
There are a variety of means to create Python extensions as described in the following table. The first two entries for CPython and PyBind11 are what has been discussed in this article already.
Approach | Vintage | Representative user(s) | Pro(s) | Con(s) |
---|---|---|---|---|
C/C++ extension modules for CPython | 1991 | Standard Library | Extensive documentation and tutorials. Total control. | Compilation, portability, reference management. High C knowledge. |
PyBind11 (Recommended for C++) | 2015 | Lightweight, header-only library for creating Python bindings of existing C++ code. Few dependencies. PyPy compatibility. | Newer, less mature. Heavy use of C++11 features. Short list of supported compilers (Visual Studio is included). | |
Cython (Recommended for C) | 2007 | gevent, kivy | Python-like. Highly mature. High performance. | Compilation, new syntax, new toolchain. |
Boost.Python | 2002 | Works with just about every C++ compiler. | Large and complex suite of libraries; contains many workarounds for old compilers. | |
ctypes | 2003 | oscrypto | No compilation, wide availability. | Accessing and mutating C structures cumbersome and error prone. |
SWIG | 1996 | crfsuite | Generate bindings for many languages at once. | Excessive overhead if Python is the only target. |
cffi | 2013 | cryptography, pypy | Ease of integration, PyPy compatibility. | Newer, less mature. |
cppyy | 2017 | Similar to cffi using C++. | Newer, may have some issues with VS 2017. |
See also
The completed sample from this walkthrough can be found on python-samples-vs-cpp-extension (GitHub).