如何向scipy.LowLevelCallable函数正确传递额外参数?
问题分析与修复方案
你的代码存在三个关键问题,导致无法正确读取user_data:
1. Python中绑定的C函数名不匹配
C代码里定义的函数是my_filter,但Python脚本里调用的是clib.max_filter,这会导致绑定到错误的函数(或未定义符号),引发未定义行为。
2. C函数的printf格式符错误
你用%ld(长整数格式)打印double类型变量,格式符不匹配会导致输出错误值。
3. Python中参数类型定义不匹配
C函数的第二个参数是intptr_t类型,但Python里argtypes中对应的是ctypes.c_long,intptr_t应对应ctypes.c_intptr_t,类型不匹配会破坏参数传递的栈结构,导致后续参数(包括user_data)读取错误。
修改后的Python脚本
from scipy import LowLevelCallable, ndimage import numpy as np import ctypes clib = ctypes.cdll.LoadLibrary('path_to_my_file/my_filter.so') # 修正:绑定正确的函数名my_filter clib.my_filter.restype = ctypes.c_int clib.my_filter.argtypes = ( ctypes.POINTER(ctypes.c_double), ctypes.c_intptr_t, # 修正:用c_intptr_t匹配C的intptr_t ctypes.POINTER(ctypes.c_double), ctypes.c_void_p ) my_user_data = ctypes.c_double(12345) ptr = ctypes.cast(ctypes.pointer(my_user_data), ctypes.c_void_p) # 修正:使用正确的函数名创建LowLevelCallable max_filter_llc = LowLevelCallable(clib.my_filter, ptr) image = np.random.random((1, 1)) footprint = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]], dtype=bool) mask = ndimage.generic_filter(image, max_filter_llc, footprint=footprint)
修改后的C代码
#include <math.h> #include <stdint.h> #include <stdio.h> int my_filter( double * buffer, intptr_t filter_size, double * return_value, void * user_data ) { double x; x = *(double *)(user_data); // 修正:用%f打印double类型变量 printf("my user_data input is: %f\n", x); // 可选:给return_value赋值,避免未定义行为 *return_value = x; return 1; }
额外注意事项
- 编译C代码时生成正确的共享库,示例gcc命令:
gcc -shared -fPIC -o my_filter.so my_filter.c - 确保
my_user_data在调用generic_filter时处于存活状态(当前代码作用域内无问题),避免被Python垃圾回收。
内容的提问来源于stack exchange,提问作者Yes
相关产品推荐
相关产品推荐

