<jupyter_start><jupyter_text>use ctypes使用ctypes调用C动态库，如果调用C++动态库，参数必须符合类型  动态库编译- Windows可直接使用CMake- Linux可直接使用gcc命令编译，也可使用CMake<jupyter_code>cat /proc/version
cd c_src
gcc sample.c -shared -fPIC -o libsample.so
mv -f libsample.so ../ctypes/lib
cd ../ctypes
python example.py<jupyter_output>7
1
0
(5, 2)
2.0
4.242640687119285<jupyter_text>基本数据类型参数<jupyter_code># int类型
import ctypes
import os

_path = './lib/libsample.dll'
_mod = ctypes.cdll.LoadLibrary(_path)
# int gcd(int, int)
gcd = _mod.gcd
gcd.argtypes = (ctypes.c_int, ctypes.c_int)
# 指定输入参数类型，将python的int使用ctypes转换为c_int,适合c语言的类型
gcd.restype = ctypes.c_int
# 指定返回参数类型，默认为c_int
print(gcd(35,42))<jupyter_output>7<jupyter_text>数组类型参数<jupyter_code># int数组
import ctypes
import os

_path = './lib/libsample.dll'
_mod = ctypes.cdll.LoadLibrary(_path)
get_elem = _mod.get_elem
get_elem.argtypes = (ctypes.Array,ctypes.c_int)
get_elem.restype = ctypes.c_int
int_array_10=ctypes.c_int*10
intput_array=int_array_10()
index =ctypes.c_int(2)
intput_array[2]=ctypes.c_int(5)
elem = get_elem(intput_array,index)
print(elem)<jupyter_output>5<jupyter_text>普通指针类型参数<jupyter_code># int指针
import ctypes
import os

_path = './lib/libsample.dll'
_mod = ctypes.cdll.LoadLibrary(_path)
divide = _mod.divide
# int divide(int, int, int *),整型指针转换
# divide.argtypes = (ctypes.c_int,ctypes.c_int,ctypes.c_int)
# 指定输入参数类型
divide.argtypes = (ctypes.c_int,ctypes.c_int,ctypes.POINTER(ctypes.c_int))
# divide.restype
# 若无返回值,或者不接收,可不制定返回值类型
# x = 0 
# x = 0,违反python之中整数不可修改
x = ctypes.c_int()
divide(10,3,x)
# bytez转int指针
import ctypes

a = (ctypes.c_byte * 4)()
print(a)
ctypes.cast(a, ctypes.POINTER(ctypes.c_int))
# cast()函数可用于将ctypes实例转换为指向不同ctypes数据类型的指针
# double指针
import ctypes

nums = [1, 2, 3]
print(*nums)
# 向函数传递参数，*将变量中可迭代对象的元素拆解出来,
# 作为独立的参数第传给函数

print('列表元素个数：',len(nums))

a = (ctypes.c_double * len(nums))(*nums)
# 将list中每个元素转化为数组中的元素
print(a)
# numpy转double指针
import numpy
import ctypes

a = numpy.array([1,2,3])
print(a)
a = a.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
# ctypes.data_as返回转换为特定c类型对象的数据指针,为其缓冲区地址
# 内部任然是调用cast()
print(a)<jupyter_output>[1 2 3]
<__main__.LP_c_double object at 0x00000274E9167548><jupyter_text>结构体类型参数<jupyter_code># 结构体
import ctypes
import os

_path = './lib/libsample.dll'
_mod = ctypes.cdll.LoadLibrary(_path)

class Point(ctypes.Structure):
  _fields_ = [('x',ctypes.c_double),('y',ctypes.c_double)]
# 需要定义一个类，包含相应的字段和类型，与c中结构体字段类型相对应

distance = _mod.distance
distance.argtypes = (ctypes.POINTER(Point),ctypes.POINTER(Point))
distance.restype = ctypes.c_double
# 指定返回值类型

p1 = Point(1,2)
p2 = Point(4,5)
distance(p1,p2)<jupyter_output><empty_output><jupyter_text>字符串类型参数<jupyter_code># 字符串
import ctypes
import os

_path = './lib/libsample.dll'
_mod = ctypes.cdll.LoadLibrary(_path)
reverse = _mod.reverse
# char* reverse(char *),字符串指针类型转换
# reverse.argtypes = (ctypes.c_char_p,)
# 如果只有1个参数,需要加",",元组特性
reverse.argtypes = [ctypes.c_char_p]
reverse.restype = ctypes.c_char_p

# inptu_str = ctypes.c_char_p("test_demo".encode("utf-8"))
inptu_str = ctypes.c_char_p(bytes("hello", 'utf-8'))
res=reverse(inptu_str).decode('utf-8')
print(res)<jupyter_output>olleh<jupyter_text>函数指针类型参数<jupyter_code># 函数指针
import ctypes
import platform

# void qsort (void* base, size_t num, size_t size,int (*compar)(const int*,const int*));
# 回调函数原型int compar(const int*,const int*)
cdll_names={
  'Linux':'lib.dylib',
  'Windows':'msvcrt.dll'
}
path = cdll_names[platform.system()]
print(path)
cdll = ctypes.cdll.LoadLibrary(path)
# 使用CFUNCTYPE创建ctypes的函数指针类型
CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))

# 回调函数，用于给出元素之间大小的判断方法
def py_func(a, b):
  print(py_func, a, b)
  return a[0] - b[0]

array_5 = ctypes.c_int * 5
a = array_5(1, 6, 3, 2, 5)
for elem in a:
  print(elem,end="\t")
print()
# 调用的是C标准库中的qsort函数
cdll.qsort(a, len(a), ctypes.sizeof(ctypes.c_int), CMPFUNC(py_func))
for elem in a:
  print(elem,end="\t")
print()<jupyter_output>msvcrt.dll
1	6	3	2	5	
<function py_func at 0x00000274E86C6E58> <ctypes.wintypes.LP_c_long object at 0x00000274E863EE48> <ctypes.wintypes.LP_c_long object at 0x00000274EF6DF9C8>
<function py_func at 0x00000274E86C6E58> <ctypes.wintypes.LP_c_long object at 0x00000274E863EE48> <ctypes.wintypes.LP_c_long object at 0x00000274EF6DF9C8>
<function py_func at 0x00000274E86C6E58> <ctypes.wintypes.LP_c_long object at 0x00000274E863EE48> <ctypes.wintypes.LP_c_long object at 0x00000274EF6DF9C8>
<function py_func at 0x00000274E86C6E58> <ctypes.wintypes.LP_c_long object at 0x00000274E863EE48> <ctypes.wintypes.LP_c_long object at 0x00000274EF6DF9C8>
<function py_func at 0x00000274E86C6E58> <ctypes.wintypes.LP_c_long object at 0x00000274E863EE48> <ctypes.wintypes.LP_c_long object at 0x00000274EF6DF9C8>
<function py_func at 0x00000274E86C6E58> <ctypes.wintypes.LP_c_long object at 0x00000274E863EE48> <ctypes.wintypes.LP_c_long object at 0x00000274EF6DF9C8>
<function py_func at 0x00000274E86C6E58> <ctypes[...]
{'fraction_non_alphanumeric': 0.13108162444712504, 'fraction_numerical': 0.07036590269400884, 'mean_word_length': 6.947284345047923, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '303928', 'license': 'MIT', 'n_tokens_mistral': 2687, 'n_tokens_neox': 2598, 'n_words': 353, 'path': 'ctypes/test_ctypes.ipynb', 'repo_name': 'UlovHer/PythonCallCpp', 'size': '4974'}