14

我有一个用于与 C 库交互的 Python 2.7 GUI。我在 GUI 中进行了一系列设置,然后按下“开始”按钮。然后,我正在查看结果,不再需要库代码。但我想在更改库时保留所有 GUI 状态。

我导入soor dllwith ctypes,这显然会打开文件以供阅读。但是,我想显式关闭文件以便重新编译和覆盖它。然后,当我再次按下“开始”按钮时,我想导入新版本。

在最坏的情况下,我可以将文件复制到 a tempfile.NamedTemporaryFile,但随后我打开了几十个文件的句柄,我无法清理这些文件。

我可以以某种方式显式关闭文件句柄吗?或者,我可以将文件的内容读入一个StringIO对象并以某种方式指向ctypes它吗?

4

1 回答 1

8

您需要关闭 DLL 的句柄,以便首先释放它,以便您可以使用该文件,您需要获取库的句柄,然后将其传递给FreeLibraryWindows,然后您可以使用 DLL 文件执行您需要的操作:

from ctypes import *

file = CDLL('file.dll')

# do stuff here

handle = file._handle # obtain the DLL handle

windll.kernel32.FreeLibrary(handle)

预览:

这是一个测试DLL:

#include <windows.h>
#include <stdio.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {

  switch( fdwReason ) {
    case DLL_PROCESS_ATTACH:
      puts("DLL loaded");
    break;

    case DLL_PROCESS_DETACH:
      puts("DLL unloaded");
    break;

    case DLL_THREAD_ATTACH:
    break;

    case DLL_THREAD_DETACH:
    break;
  }

  return TRUE;
}

__declspec(dllexport) void function(void) {
  puts("Hello");
}

预览:

>>> from ctypes import *
>>>
>>> file = CDLL('file.dll')
DLL loaded
>>>
>>> # now it's locked
...
>>> file.function()
Hello
0
>>> windll.kernel32.FreeLibrary(file._handle)
DLL unloaded
1
>>> # not it's unlocked

在 Linux 上,您使用dlclose它将是:

from ctypes import *

file = CDLL('./file.so')

# do stuff here

handle = file._handle # obtain the SO handle

cdll.LoadLibrary('libdl.so').dlclose(handle)

这是一个类似的共享对象:

#include <stdio.h>

__attribute__((constructor)) void dlentry(void) {
  puts("SO loaded");
}

void function(void) {
  puts("Hello");
}

__attribute__((destructor)) void dlexit(void) {
  puts("SO unloaded");
}

预览:

>>> from ctypes import *
>>> 
>>> file = CDLL('./file.so')
SO loaded
>>> 
>>> file.function()
Hello
6
>>> cdll.LoadLibrary('libdl.so').dlclose(file._handle)
SO unloaded
0
>>> 
于 2013-10-23T17:20:08.560 回答