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.