You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:01:05