强制ctypes.cdll.LoadLibrary()从文件中重新加载库

时间:2018-06-21 08:38:00

标签: python dll ctypes

我有以下代码

import ctypes
lib1 = ctypes.cdll.LoadLibrary("./mylib.so")
# modify mylib.so (code generation and compilation) or even delete it
lib2 = ctypes.cdll.LoadLibrary("./mylib.so")

问题在于lib2是指原始共享库,而不是新共享库。如果我在两次调用之间删除mylib.so,我不会出错。

使用ctypes._reset_cache()无济于事。

如何告诉ctypes实际上是从硬盘上重新加载库的?

2 个答案:

答案 0 :(得分:2)

我不知道如何指示 ctypes 如何卸载库(在[Python 3]: ctypes - A foreign function library for Python上找不到方法,但这并不意味着没有一个方法。 )。

可以通过强制加载器(减少库的引用​​计数并)通过[man7]: DLCLOSE(3P)进行卸载来手动完成操作(有关加载/卸载库的更多信息,请阅读[man7]: DLOPEN(3))。

dll.c

<Toolbar id={this.state.id}/>

code.py

#include <stdio.h>

int func0(int arg0) {
    int alter_factor = 2;
    printf("From C - arg0: %d, alter_factor: %d\n", arg0, alter_factor);
    return arg0 * alter_factor;
}

输出

#!/usr/bin/env python3

import sys
import ctypes


DLL_NAME = "./dll.so"


def handle_dll(dll_name=DLL_NAME):
    dll_dll = ctypes.CDLL(dll_name)
    func0_func = dll_dll.func0
    func0_func.argtypes = [ctypes.c_int]
    func0_func.restype = ctypes.c_int
    return dll_dll, func0_func


def main():
    dlclose_func = ctypes.CDLL(None).dlclose
    dlclose_func.argtypes = [ctypes.c_void_p]
    dlclose_func.restype = ctypes.c_int

    dll, func0 = handle_dll()
    res = func0(42)
    print(res)
    dlclose_func(dll._handle)
    input("In another terminal, modify the C code (e.g. change `alter_factor`), recompile (gcc -fPIC -shared -o dll.so dll.c), and when done press ENTER here...")
    dll, func0 = handle_dll()
    res = func0(42)
    print(res)


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

答案 1 :(得分:0)

稍微简化CristiFatis answer,我写了一个封闭库函数。以下代码可用于在您的共享库中进行开发,并从python调用它(最新版本)。

import ctypes
def ctypesCloseLibrary(lib):
    dlclose_func = ctypes.CDLL(None).dlclose
    dlclose_func.argtypes = [ctypes.c_void_p]
    dlclose_func.restype = ctypes.c_int

    dlclose_func(lib._handle)

if __name__== "__main__":
    lib = ctypes.cdll.LoadLibrary('./mylib.so')

    # do things with lib_MyClass

    ctypesCloseLibrary(lib)

当您希望ctypesCloseLibrary重新加载lib时,只需调用lib = ctypes.cdll.LoadLibrary('./mylib.so')