Skip to content Skip to sidebar Skip to footer

Forcing Ctypes.cdll.loadlibrary() To Reload Library From File

I have the following code import ctypes lib1 = ctypes.cdll.LoadLibrary('./mylib.so') # modify mylib.so (code generation and compilation) or even delete it lib2 = ctypes.cdll.LoadLi

Solution 1:

I don't know how to instruct ctypes how to unload a library (didn't find a way on [Python 3]: ctypes - A foreign function library for Python, but that doesn't mean that there isn't one).

It can be done manually, by forcing the loader to (decrement the library's reference count and) unload it via [man7]: DLCLOSE(3P) (also read [man7]: DLOPEN(3) for additional info on loading / unloading libraries).

dll.c:

#include<stdio.h>intfunc0(int arg0) {
    int alter_factor = 2;
    printf("From C - arg0: %d, alter_factor: %d\n", arg0, alter_factor);
    return arg0 * alter_factor;
}

code.py:

#!/usr/bin/env python3import sys
import ctypes


DLL_NAME = "./dll.so"defhandle_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


defmain():
    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()

Output:

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050964033]> python3 code.py
Python 3.5.2 (default, Nov 232017, 16:37:01)
[GCC 5.4.020160609] on linux

From C - arg0:42, alter_factor:284
In another terminal, modify the C code (e.g. change `alter_factor`), recompile (gcc -fPIC -shared -o dll.so dll.c), andwhen done press ENTER here...
From C - arg0:42, alter_factor:3126

Solution 2:

Simplifying CristiFatis answer a bit, I wrote a close-library function. The following code can be used to develop in your shared library and call it (in the most recent version) from 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)

Just call ctypesCloseLibrary when you want lib to be reloadable by lib = ctypes.cdll.LoadLibrary('./mylib.so').

Post a Comment for "Forcing Ctypes.cdll.loadlibrary() To Reload Library From File"