Toccata in Nowhere.

Python 调用 C/C++ 函数

2019.11.04

Python Call C/C++ functions

Packages

import ctypes

Methods

Compile of C/C++ function to dynamic library

For C

gcc functionsName.c -fPIC -shared -o libName.so

For C++

g++ functionsName.cpp -fPIC -shared -o libName.so

Important: the dynamic library of C++ MUST be compiled as C style, the solution as below:

macro definition:

#define CEXT extern "C"
// then add the macro keywords before function name:
CEXT void helloWorld(){
...
}

Import

import ctypes

functionBranch = ctypes.cdll.LoadLibrary("./libName.so")

Declare the data type of return value and parameters

functionBranch.funcName.restype = ctypes.c_float

Optional Type:

ctypes type C type Python Type
c_char char 1-character string
c_wchar wchar_t 1-character unicode string
c_byte char int/long
c_ubyte unsigned char int/long
c_bool bool bool
c_short short int/long
c_ushort unsigned short int/long
c_int int int/long
c_uint unsigned int int/long
c_long long int/long
c_ulong unsigned long int/long
c_longlong __int64 or longlong int/long
c_ulonglong unsigned __int64 or unsigned long long int/long
c_float float float
c_double double float
c_longdouble long double float float
c_char_p char * string or None
c_wchar_p wchar_t * unicode or None
c_void_p void * int/long or None

For pointer type: add _p after the type name, such as c_int_p of int*.

Declaration of C-type arrays / Matrix as Argument

An effective way is to import numpy.ctypeslib as npct and use the ndpointer function to declare a pointer:

import ctypes
import numpy as np
import numpy.ctypeslib as npct

radiats = ctypes.cdll.LoadLibrary("./libradiats.so")
radiats.dc_radiat.argtypes = [ctypes.c_float, ctypes.c_float, ctypes.c_float, npct.ndpointer(dtype = ctypes.c_float, ndim = 2, flags="C_CONTIGUOUS")]

aa = np.zeros([3, 3], dtype = ctypes.c_float)
strike = 20
dip = 30
rake = 0
radiats.dc_radiat(strike,dip,rake,aa)
print(aa)

Also, the declaration of argument is shown above. The ndpointer function declared a 2-D pointer with the data type ctypes.c_float

To Be Noticed

The bit width of float for C/C++ programming language is 32, but for Python, not only the float but also np.float,it is 64. So REMEMBER to set the same data type when declaring the restype or argtypes, especially when the matrix transmission existed in the argments.