阅读mmdeploy源码时关于ctypes.CDLL(lib_path)的技术疑问
问题解答
为什么ctypes.CDLL(lib_path)未赋值却能调用插件中的函数/变量?
首先纠正一个误解:ctypes.CDLL(lib_path)是有返回值的,它会返回一个代表加载后DLL的ctypes.CDLL对象。代码里没把这个对象赋值给变量,不代表DLL没起作用——核心原因在于这类自定义插件DLL的设计逻辑:
- 多数mmdeploy自定义插件在被加载时,会自动执行内部的初始化代码(比如DLL的
DllMain函数,或者插件导出的专门注册函数),把自身的功能(算子、函数、变量等)注册到mmdeploy的核心框架中。 - 之后Python层调用插件功能时,并不是直接通过
ctypes.CDLL对象,而是通过mmdeploy提供的统一API间接调用——这些API已经能访问到插件注册后的功能,所以不需要持有那个临时的CDLL对象。
举个直观例子:插件DLL里可能有个register_my_custom_op()函数,加载DLL时自动执行,把自定义算子注册到mmdeploy的算子管理器里,之后你调用mmdeploy.inference()时,框架就能找到并执行这个插件里的算子,全程不需要你操作那个CDLL对象。
加载的DLL存放在哪里?为什么locals()/globals()找不到?
- 内存层面:
ctypes.CDLL加载的DLL会被映射到当前Python进程的地址空间中,属于系统级别的进程内存,不是Python变量能直接存储的“位置”。 - Python变量层面:因为代码里没把
ctypes.CDLL(lib_path)的返回值赋值给任何变量,这个临时的CDLL对象会在语句执行完后,被Python的垃圾回收机制标记为可回收对象(如果没有其他隐式引用的话)。但DLL本身不会被卸载——系统会维护一个DLL加载计数,只要计数不为0(比如框架核心模块还在引用插件的功能),DLL就会一直留在进程内存里。 - 正因为没把
CDLL对象存入局部或全局变量,所以print(locals())和print(globals())自然找不到相关痕迹。
内容的提问来源于stack exchange,提问作者machine_handler
相关产品推荐
相关产品推荐

