我正在编写一个Python,它通过ctype从OS上调用Security.framework函数。
我能够用Python创建一个CFDictionaryRef和CFStringRef,并将字符串存储在字典中,但现在我正在添加Security.framework查询对象(kSecClass、kSecMatchLimit、kSecReturnAttributes、…)我得到了以下坠机:
objc[28201]: Method cache corrupted. This may be a message to an invalid object, or a memory error somewhere else.
objc[28201]: receiver 0x7fff724fcdf8, SEL 0x7fff8d814fe5, isa 0x7fff724f5f90, cache 0x7fff724f5fa0, buckets 0x7fff8842ffe3, mask 0x5, occupied 0x0, wrap bucket 0x7fff8842ffe3
objc[28201]: receiver 0 bytes, buckets 0 bytes
objc[28201]: selector 'hash'
objc[28201]: isa '(null)'
objc[28201]: Method cache corrupted.
zsh: illegal hardware instruction python kc.py我尝试使用包含对象的ctype数组调用CFDictionaryCreate(),并调用CFMutableDictionaryCreate()然后CFDictionarySetValue。见下文。
import ctypes
import ctypes.util
from ctypes import CFUNCTYPE
security = ctypes.CDLL(ctypes.util.find_library('Security'))
foundation = ctypes.CDLL(ctypes.util.find_library('Foundation'))
CFDictionaryRef = ctypes.c_void_p
CFMutableDictionaryRef = ctypes.c_void_p
CFTypeRef = ctypes.c_void_p
CFIndex = ctypes.c_long
CFDictionaryCreate = CFUNCTYPE(CFDictionaryRef, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, CFIndex, ctypes.c_void_p, ctypes.c_void_p)(('CFDictionaryCreate', foundation))
CFDictionaryCreateMutable = CFUNCTYPE(CFMutableDictionaryRef, CFIndex, ctypes.c_void_p, ctypes.c_void_p)(('CFDictionaryCreateMutable', foundation))
CFDictionarySetValue = CFUNCTYPE(CFMutableDictionaryRef, ctypes.c_void_p, ctypes.c_void_p)(('CFDictionarySetValue', foundation))
def createCFDictionary(items):
"""
Create a CFDictionaryRef from items = [(CFTypeRef, CFTypeRef), ...]
"""
# Create C arrays for the keys and values (which are cast as CFTypeRefs).
keys_array = (CFTypeRef * len(items))(*[ctypes.cast(k, CFTypeRef) for k, v in items])
values_array = (CFTypeRef * len(items))(*[ctypes.cast(v, CFTypeRef) for k, v in items])
return CFDictionaryCreate(None,
keys_array, values_array, len(items),
foundation.kCFTypeDictionaryKeyCallBacks, foundation.kCFTypeDictionaryValueCallBacks)
# 1. Create a CFDictionary with the items in it (crashes).
query = createCFDictionary([(security.kSecClass, security.kSecClassCertificate)])
# 2a. Create a CFMutableDictionary.
query = CFDictionaryCreateMutable(0, foundation.kCFTypeDictionaryKeyCallBacks, foundation.kCFTypeDictionaryValueCallBacks)
# 2b. Add items to it (crashes).
CFDictionarySetValue(query, security.kSecClass, security.kSecClassCertificate)如果这是一种更简单的解决方案,我很乐意使用PyObjC而不是ctype;然而,我对它不太熟悉,也无法导入Security.framework。
OS 10.9.2,Python2.7.5(随OS一起包括)。
发布于 2014-05-14 14:21:56
我正在调查第二个案例,因为它看起来更简单。
您的CFDictionarySetValue缺少了dict参数。修复后,security.kSecClass似乎实际上返回了一个函数引用,这是错误的。我认为你需要:
ctypes.c_void_p.in_dll(foundation, 'kSecClass')这将导致将正确的值传递给函数(如lldb中所示)。
不知何故,kCFTypeDictionaryKeyCallBacks结构仍然无法使用该机制,这可能是因为符号实际上指向的是结构,而不是指向结构的指针。我想不出任何方法让ctype返回符号所代表的实际地址(这就是您想传递给CFDictionaryCreateMutable的地址),而不是那个符号的值( 0,因为这是该结构的第一个成员的值)。
您可以自己构造回调,这应该更容易一些,因为您可以在ctype中定义struct类型,然后获取所需的函数。
https://stackoverflow.com/questions/23642046
复制相似问题