(with code) getting started | How to use Python to call C/C++ code

Editor's Recommendation

In the previous article, we introduced how to use C/C++ to call Python scripts . In this article, we will fill in another common problem in development. When we use Python for development, because some algorithms are computationally intensive, it will cause too much running time. At this time, we can implement these algorithms in C/C++ language, thereby reducing the running time of the program.

It is very convenient to use Python, but it is not as efficient as C/C++; moreover, sometimes we want to protect some critical codes, we can compile these codes into C/C++ dynamic libraries, and then use Python Going to call can achieve this goal very well.

Generally, there are two commonly used implementation methods:
use Python extension to write C/C++ code, and then use import to call the dynamic library. Use
Python's ctypes module to directly load C/C++ dynamic library (using the common C/C++ code writing method).

Although they are all compiled as dynamic libraries, the big gap lies in the writing of C/C++ code.

The difference between different implementation methods

The first method is an extension mechanism for Python to integrate other languages, not limited to the C/C++ language. I personally feel that the second method is easier to understand and implement (usually it does not need to modify the existing C/C++ Code rewriting, or only a small amount of rewriting), so today I will introduce the specific implementation process in this way.

For the implementation of the first method, you can refer to: https://docs.python.org/zh-cn/3/c-api/intro.html

At this point, many students may say Cython, yes, Cython will solve a series of problems of Python / ctypes (such as speed bottleneck), but too much learning cost may not be acceptable when you start doing some simple things , and ctypes is better at doing simple things and running fast, especially for programmers with C/C++ and Python experience. For the choice of Cython and ctypes, you can refer to here: https://www.codenong.com/1942298/

Briefly introduce the library

The essence of a library is a packaged code package, which can usually be divided into static libraries (.lib .a) and dynamic libraries (.dll .so). The former is generally the suffix in the windows environment, and the latter is the suffix in the linux environment. . The static library will be compiled into the final executable file when the main program is compiled, while the dynamic library will search for relevant content when calling. Because ctypes has no way to call static libraries, we will compile C/C++ into dynamic libraries this time.

Basic usage

Personally, I feel that the advantage of using ctypes is that it is convenient, and a small modification can lead to a great performance improvement. It is an optimal choice under the balance between efficiency and performance. The calling process is generally divided into two steps:
1. Compile the C/C++ code into a dynamic library;
2. Use Python to call the corresponding dynamic library.

Compile C/C++ code into a dynamic library

CMake remember to modify:

add_library(c_library SHARED src/c_library.cpp)

SHARED here means the dynamic link library.

ctypes won't know about #define constants and stuff in the library you're using, only functions, so you'll have to redefine those constants in your own code.

A simple summation code looks like this (named: c_library.cpp):

#include <stdio.h>

extern "C"
{
    
    
    int add_int(int num1, int num2)
{
    
    
        return num1 + num2;
    }

    float add_float(float num1, float num2)
{
    
    
        return num1 + num2;
    }
}

Pay special attention to the need to add the prefix extern "C" to the function declaration when calling the C++ function. This is because C++ supports the function overloading function, and the function name will be changed during compilation. So when the function is declared, we add the prefix extern "C" by default to ensure that the code is compiled in the C way.

Compile it, and the generated dynamic library is shown in the figure below:

insert image description here

Use Python to call dynamic libraries

The process of Python calling a dynamic link library is generally divided into steps:
1. Load the dynamic link library;
2. Convert the input to a C-compatible data type;
3. Convert the output to a C-compatible data type;
4. Call the dynamic library function.

The full code looks like this:

import ctypes
import os
import sys

#Load the shared object file
if sys.platform == "win32":
    c_library = ctypes.CDLL(os.path.abspath(
        '.')+"/out/build/x64-Debug/c_cxx/c_library/libc_library.dll")
    print
elif sys.platform == "linux":
    c_library = ctypes.CDLL(os.path.abspath(
        '.')+"/build/c_cxx/c_library/libc_library.so")

#Find sum of integers
res_int = c_library.add_int(4, 5)
print("Sum is : " + str(res_int))

#Find sum of floats
a = ctypes.c_float(5.5)  # 输入转换为C兼容的数据类型
b = ctypes.c_float(4.1)

c_library.add_float.restype = ctypes.c_float  # 输出转换为C兼容的数据类型

print("Sum is : ", str(c_library.add_float(a, b)))

If I remember correctly, the int type does not need to be converted, so I didn't write the code.

Run the Python code, the result is as follows:

insert image description here
For more ctypes related operations, please refer to: https://docs.python.org/3/library/ctypes.html

Correspondence table between commonly used variable types and C types in ctypes:

insert image description here

References

1.https://zhuanlan.zhihu.com/p/36772947
2.https://blog.csdn.net/u012247418/article/details/80170690

Guess you like

Origin blog.csdn.net/weixin_41006390/article/details/126459715