Python 使用ctypes从CoreFoundation调用带有参数的函数
我正在尝试使用Python中的ctypes从MacOSX中的CoreFoundation框架访问CoreMidi函数 当我调用一个没有任何参数的函数时,一切都很顺利。例如,以下代码:Python 使用ctypes从CoreFoundation调用带有参数的函数,python,macos,ctypes,coremidi,Python,Macos,Ctypes,Coremidi,我正在尝试使用Python中的ctypes从MacOSX中的CoreFoundation框架访问CoreMidi函数 当我调用一个没有任何参数的函数时,一切都很顺利。例如,以下代码: from ctypes import * core_midi = cdll.LoadLibrary("/System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI") numOfDevices = core_midi.MIDIGetNumberO
from ctypes import *
core_midi = cdll.LoadLibrary("/System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI")
numOfDevices = core_midi.MIDIGetNumberOfDevices()
print numOfDevices
返回
3
这是我的计算机中MIDI设备的数量
但是,我无法执行需要参数的函数。检查此示例(EDIT:正如eryksun指出的,我使用了char*作为客户端名称,函数原型要求使用CFString。我在下面的代码示例中更正了这一点,但仍然得到相同的错误):
这段代码根本不打印任何内容,甚至不会引发异常。midclientcreate函数的原型是:
extern OSStatus MIDIClientCreate(
CFStringRef name,
MIDINotifyProc notifyProc,
void *notifyRefCon,
MIDIClientRef *outClient );
MIDIClientRef被定义为UInt32,据我所知,它接收指向已创建的MIDIClient结构的指针,这就是我使用byref()将其作为参数传递的原因。如果我只传递不带byref()的变量,函数调用将返回一个值-50,这可能表示出现了一些奇怪的错误
编辑:我不确定是否正确创建了CFString。我试图用下面的代码测试结果,但它没有在屏幕上打印任何内容
client_name = core_foundation.CFStringCreateWithCString(None, "MIDI Client", 0)
cstr = ctypes.create_string_buffer(20)
core_foundation.CFStringGetCString(client_name, cstr, 20, 0)
print cstr
谢谢
编辑:由艾尔克森回答
当然,我不知道这一点,但设置指针并不像我天真的例子那样明显
class _CFString(Structure):
pass
cf_path = ctypes.util.find_library("CoreFoundation")
cm_path = ctypes.util.find_library("CoreMIDI")
core_foundation = ctypes.cdll.LoadLibrary(cf_path)
core_midi = ctypes.cdll.LoadLibrary(cm_path)
CFStringRef = POINTER(_CFString)
midi_client = ctypes.c_uint()
core_foundation.CFStringCreateWithCString.restype = CFStringRef
core_foundation.CFStringCreateWithCString.argtypes = [c_void_p, c_char_p, c_uint32]
client_name = core_foundation.CFStringCreateWithCString(None, "MIDI Client", 0)
core_midi.MIDIClientCreate.argtypes = [CFStringRef, c_void_p, c_void_p, POINTER(c_uint32)]
result = core_midi.MIDIClientCreate(client_name, None, None, byref(midi_client))
print midi_client
print result
实际上,我认为restype和argtypes不会影响函数的执行方式或参数的传递方式,但它们似乎确实会影响
上述代码导致:
c_uint(4657178L)
0
也就是说,我的MIDI客户机是在某处创建的,函数返回时不会出错。
再次感谢埃里克森 哦,好的,艾里克森。我尝试使用CFStringCreateWithBytes创建CFString,但仍然没有成功。为了反映这一点,我对问题进行了编辑。我想我搞乱了byref参数…嘿,eryksun,就是这样,非常感谢!写一个答案,这样我就可以把你标记为回答者。顺便说一句,只需重新设置样式就足够了。。。我认为您对64位结果指针被截断的看法是正确的。。。
c_uint(4657178L)
0