提问人:YKdvd 提问时间:3/19/2023 更新时间:3/19/2023 访问量:77
CFFI等同于ctypes “in_dll()”?
cffi equivalent of ctypes "in_dll()"?
问:
在 MacOS 上访问框架 dll 时,通常定义了很多字符串常量,使用 ctypes,我可以做这样的事情来在运行时检索任意一个常量,而不必定义它们:
CFString = c_void_p
CFStringRef = POINTER(CFString)
my_dll = CDLL(...)
s1 = CFStringRef.in_dll(my_dll, "kSomeSpecificConstant")
s2 = CFStringRef.in_dll(my_dll, "kSomeOtherConstant)
使用 cffi,我可以做这样的事情来显式定义事物:
my_dll = cffi.FFI()
my_dll.cref("""
typedef void *CFTypeRef;
typedef CFTypeRef CFStringRef;
extern CFStringRef kSomeSpecificConstant
extern CFStringRef kSomeOtherConstant
""")
但是似乎没有一种机制可以像 in_dll() 那样对符号进行运行时查找?
答:
1赞
Armin Rigo
3/19/2023
#1
在 API 模式 () 中,在 和 完成后无法直接进行运行时查找。在 ABI 模式 () 中,您可以通过再次调用来声明符号来做到这一点,然后我很确定可以通过先前返回的 .这有点黑客,但它应该有效。还有一些方法可以通过在 CFFI 运行时中直接调用一些内部函数来实现,但同样只能在 ABI 模式下(在 API 模式下,我们首先没有 DLL 的动态句柄;实际上根本不需要单独的 DLL)。ffi.set_source()
ffi.set_source()
ffi.compile()
lib=ffi.dlopen()
ffi.cdef()
lib
但是,进行动态符号查找的正确方法是以与在 C 中相同的方式进行查找:使用标准库函数,例如 .使用 CFFI 时,您可以通过将声明添加到 和 以 开头的相关函数来做到这一点。有关 MacOSX 的详细信息,请查看手册页;这些标准 POSIX 函数以及它们在 Mac 上用于框架的方式可能存在差异。dlsym()
void *dlsym(void *handle, const char *symbol);
ffi.cdef()
void *dlopen(const char *filename, int flags)
评论
0赞
YKdvd
3/19/2023
非常感谢。在访问时捕获异常,使用 cdef() 添加符号,然后再次尝试实际上浮现在脑海中,但正如您所说,这似乎有点黑客。我假设可以在 ffi.dlopen() 之后进行额外的 cdef() 调用。我将考虑使用 dlsym 进行设置 - 再次感谢您的指针...... :)
0赞
YKdvd
3/20/2023
鉴于“mydll”来自ffi.dlopen(dllpath),该ffi.dlopen(dllpath)为“dlsym”定义了cdef(),有没有办法从“mydll”获取dll句柄以传递给dlsym()?类似的东西:symbol = mydll.dlsym(mydll.get_the_handle(), “someSymbolName”) 看起来 FFILibrary 类有效地隐藏了它创建的“backendlib”,我认为句柄在哪里?还是我必须 dlopen 和 dlclose 我自己的句柄?
0赞
Armin Rigo
3/20/2023
你必须使用一些构造的字符串,这有点慢,但每个符号只做一次,或者你必须使用独立于 cffi 的句柄来获得自己的句柄。至少我是这么想的;也许你可以绕过它,但这实际上是在挖掘 CFFI 的未记录、不支持的内部结构。ffi.cdef("...")
dlopen()
backendlib
评论