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

Python类中定义调用C DLL方法的正确方式及常见报错解决

问题原因逐一解析

1. 第一次修改报AttributeError的原因

你将func_1、func_2定义在了__init__方法内部,这两个属于函数内部的局部函数,只会在__init__执行时存在,不会成为类的实例方法,外部通过实例对象自然访问不到。

2. 第二次修改输出None的原因

你修改后的func_1、func_2只完成了DLL方法的属性配置(设置argtype、restype),既没有实际调用DLL的方法,也没有写return返回结果,Python函数默认返回None,所以输出都是空值。

3. 参数定义语法错误的原因

Python函数的参数位置只能写形参名,不能直接写类型。如果要加类型标注,正确的写法是在形参名后加冒号标注类型:

def func_1(self, var1: ctypes.c_uint8, var2: ctypes.c_uint8):

但这里其实不需要额外标注,你给DLL方法设置的argtype会自动完成参数类型转换,只要传入的参数值符合类型要求即可。

正确实现方案

这里提供两种常用的实现方式,你可以根据需求选择:

方案1:初始化时一次性完成所有DLL方法配置(推荐,性能更高)

和你原始逻辑一致,只是拆分了配置逻辑,避免__init__代码冗余:

import ctypes

class my_outer_class:
    def __init__(self, dll_path: str = r'C:\\Users\OneDrive\HelloWorld\HelloWorld\loc\Debug\HelloWorld.dll'):
        # 加载DLL
        self._dll = ctypes.WinDLL(dll_path)
        # 批量初始化DLL方法
        self._init_dll_functions()
    
    def _init_dll_functions(self):
        """封装DLL方法的初始化逻辑,私有方法避免外部随意调用"""
        # 配置function_1
        self.py_function_1 = self._dll.function_1
        self.py_function_1.argtype = (ctypes.c_uint8, ctypes.c_uint8)
        self.py_function_1.restype = ctypes.c_int
        
        # 配置function_2
        self.py_function_2 = self._dll.function_2
        self.py_function_2.argtype = (ctypes.c_uint8, ctypes.c_uint8)
        self.py_function_2.restype = ctypes.c_int

调用方式和你原始版本完全一致:

import hello

myapi = hello.my_outer_class()
result = myapi.py_function_1(123, 123)
print(result) # 输出1
result = myapi.py_function_2(123, 123)
print(result) # 输出0

方案2:调用时懒加载配置(适合DLL方法非常多的场景)

如果你的DLL有几十上百个方法,不需要每次初始化都全部配置,可以用懒加载的方式,第一次调用时才完成配置:

import ctypes

class my_outer_class:
    def __init__(self, dll_path: str = r'C:\\Users\OneDrive\HelloWorld\HelloWorld\loc\Debug\HelloWorld.dll'):
        self._dll = ctypes.WinDLL(dll_path)
        self._py_function_1 = None
        self._py_function_2 = None
    
    def func_1(self, var1: int, var2: int) -> int:
        # 第一次调用时初始化
        if not self._py_function_1:
            self._py_function_1 = self._dll.function_1
            self._py_function_1.argtype = (ctypes.c_uint8, ctypes.c_uint8)
            self._py_function_1.restype = ctypes.c_int
        # 调用DLL方法并返回结果
        return self._py_function_1(var1, var2)
    
    def func_2(self, var1: int, var2: int) -> int:
        if not self._py_function_2:
            self._py_function_2 = self._dll.function_2
            self._py_function_2.argtype = (ctypes.c_uint8, ctypes.c_uint8)
            self._py_function_2.restype = ctypes.c_int
        return self._py_function_2(var1, var2)

调用方式和你修改后的测试代码一致:

import hello

myapi = hello.my_outer_class()
result = myapi.func_1(123, 123)
print(result) # 输出1
result = myapi.func_2(123, 123)
print(result) # 输出0

最佳实践建议

  • DLL路径尽量用原始字符串(前缀加r),避免转义字符出错
  • DLL方法的argtype和restype只需要配置一次即可,不需要每次调用都重复配置
  • 私有方法/属性加下划线前缀,和对外暴露的公共方法区分开

内容的提问来源于stack exchange,提问作者pekoms

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:06:04