Bloggers have stepped through many holes, many tutorials are built by Visual Studio (non CMake project), many tutorials are Python 2, and some common errors (mainly from environment configuration problems). This article is mainly to teach Mengxin how to build with official use cases (there are many bloody and tearful histories of stepping on the pit in person)
Related tutorials
- Swig super detailed introductory tutorial (Java calls C/C++, CMake) -- updated on December 2021
- Swig super detailed introductory tutorial (Python 3 calls C/C++, CMake) -- updated on December 2021
- [start from scratch] C + + calls python (CMake, Clion, windows, including some common errors)
Environment configuration
- swig official website tutorial: http://www.swig.org/tutorial.html
swigwin download address: https://sourceforge.net/projects/swig/files/swigwin/
After installation, for convenience, you can add the installation directory to the environment variable path.
SWIG_DIR = C:\swigwin-4.0.2 SWIG_EXECUTABLE = C:\swigwin-4.0.2\swig.exe
- C + +: I use Mingw-w64 (GCC 9.3.0). If I use a higher version of python, the gcc version cannot be too low, otherwise an error will be reported. Remember to configure environment variables! Super detailed tutorial: windows installation MSYS2 (MinGW & & GCC) - updated on 2021.11
$ gcc --version Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- Python: I use Anaconda (Python 3.9.7). Configure the environment variable PYTHONHOME = C:\ProgramData\Anaconda3. https://www.anaconda.com/
- Clion: install and configure Toolchains normally. (of course, other ides can also be selected)
- Copy and rename C:/ProgramData/Anaconda3/libs/python39.lib to C:/ProgramData/Anaconda3/libs/python39_d.lib, mainly to add debug scenarios.
- Restart the computer (the environment variable must be restarted to take effect. In fact, many scenarios can take effect without restarting, but this case is necessary, and strange bug s will occur without restarting)
Examples of using CMake (C language)
Project directory structure:
We first build the following example.c file
/* File : example.c */ /* A global variable */ double Foo = 3.0; /* Compute the greatest common divisor of positive integers */ int gcd(int x, int y) { int g; g = y; while (x > 0) { g = x; x = y % x; y = g; } return g; }
Then build the example.i file
/* File : example.i */ %module example %inline %{ extern int gcd(int x, int y); extern double Foo; %}
We created CMakeLists.txt:
#/* File : CMakeLists.txt */ #Specifies the minimum version of CMake cmake_minimum_required(VERSION 3.17) project(Example) set(CMAKE_CXX_STANDARD 20) #Find the environment variable for PYTHONHOME find_package (Python3 COMPONENTS Interpreter Development) include_directories(${Python3_INCLUDE_DIRS}) link_libraries(${Python3_LIBRARIES}) #Specify the directory of your. cxx and other files include_directories(${PROJECT_SOURCE_DIR}/src) #Looking for the installed Swig is actually going to the computer to find the Swig environment you installed, so we need to install the environment in advance. find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) #Python file output directory - outdir set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/python) #Specify an output directory name to place the generated source files. For example, output exampleptyhon_ The location of the wrap.cxx file, etc set(SWIG_OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR}/cpp) #Start build swig_add_library(example LANGUAGE python SOURCES src/example.i src/example.c)
Then we reload the CMake project
Then click build:
The following is generated:
Copy these files to a new folder, and then create runme.py:
# file: runme.py import example # Call our gcd() function x = 42 y = 105 g = example.gcd(x, y) print("The gcd of %d and %d is %d" % (x, y, g)) # Manipulate the Foo global variable # Output its current value print("Foo = ", example.cvar.Foo) # Change its value example.cvar.Foo = 3.1415926 # See if the change took effect print("Foo = ", example.cvar.Foo)
Run runme:
The gcd of 42 and 105 is 21 Foo = 3.0 Foo = 3.1415926
Examples of using CMake (C + +)
Project directory structure:
We first build the following example.cxx file
/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 /* Move the shape to a new location */ void Shape::move(double dx, double dy) { x += dx; y += dy; } int Shape::nshapes = 0; double Circle::area() { return M_PI * radius * radius; } double Circle::perimeter() { return 2 * M_PI * radius; } double Square::area() { return width * width; } double Square::perimeter() { return 4 * width; }
Then build the example.i file
/* File : example.i */ %module example %{ #include "example.h" %} /* Let's just grab the original header file here */ %include "example.h"
Then build the example.h file
/* File : example.h */ class Shape { public: Shape() { nshapes++; } virtual ~Shape() { nshapes--; } double x, y; void move(double dx, double dy); virtual double area() = 0; virtual double perimeter() = 0; static int nshapes; }; class Circle : public Shape { private: double radius; public: Circle(double r) : radius(r) {} virtual double area(); virtual double perimeter(); }; class Square : public Shape { private: double width; public: Square(double w) : width(w) {} virtual double area(); virtual double perimeter(); };
We create CMakeLists.txt (note the difference between this and CMakeLists.txt in C language):
#/* File : CMakeLists.txt */ #Specifies the minimum version of CMake cmake_minimum_required(VERSION 3.17) project(Example) set(CMAKE_CXX_STANDARD 20) #Find the environment variable for PYTHONHOME find_package (Python3 COMPONENTS Interpreter Development) include_directories(${Python3_INCLUDE_DIRS}) link_libraries(${Python3_LIBRARIES}) #Specify the directory of your. cxx and other files include_directories(${PROJECT_SOURCE_DIR}/src) #Looking for the installed Swig is actually going to the computer to find the Swig environment you installed, so we need to install the environment in advance. find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) #Python file output directory - outdir set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/python) #Specify an output directory name to place the generated source files. For example, output exampleptyhon_ The location of the wrap.cxx file, etc set(SWIG_OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR}/cpp) #c + + mode set_property(SOURCE src/example.i PROPERTY CPLUSPLUS ON) #Start build swig_add_library(example LANGUAGE python SOURCES src/example.i src/example.cxx)
Then we reload the CMake project
Then click build:
The following is generated:
Copy these files to a new folder, and then create runme.java:
# file: runme.py # This file illustrates the proxy class C++ interface generated # by SWIG. import example # ----- Object creation ----- print("Creating some objects:") c = example.Circle(10) print(" Created circle", c) s = example.Square(10) print(" Created square", s) # ----- Access a static member ----- print("\nA total of", example.cvar.Shape_nshapes, "shapes were created") # ----- Member data access ----- # Set the location of the object c.x = 20 c.y = 30 s.x = -10 s.y = 5 print("\nHere is their current position:") print(" Circle = (%f, %f)" % (c.x, c.y)) print(" Square = (%f, %f)" % (s.x, s.y)) # ----- Call some methods ----- print "\nHere are some properties of the shapes:" for o in [c, s]: print(" ", o) print(" area = ", o.area()) print(" perimeter = ", o.perimeter()) # prevent o from holding a reference to the last object looked at o = None print("\nGuess I'll clean up now") # Note: this invokes the virtual destructor del c del s print(example.cvar.Shape_nshapes, "shapes remain") print("Goodbye")
Run runme:
Creating some objects: Created circle <example.Circle; proxy of <Swig Object of type 'Circle *' at 0x000001691EA1E870> > Created square <example.Square; proxy of <Swig Object of type 'Square *' at 0x000001691EA1ECC0> > A total of 2 shapes were created Here is their current position: Circle = (20.000000, 30.000000) Square = (-10.000000, 5.000000) <example.Circle; proxy of <Swig Object of type 'Circle *' at 0x000001691EA1E870> > area = 314.1592653589793 perimeter = 62.83185307179586 <example.Square; proxy of <Swig Object of type 'Square *' at 0x000001691EA1ECC0> > area = 100.0 perimeter = 40.0 Guess I'll clean up now 0 shapes remain Goodbye Process finished with exit code 0