1

我正在尝试在 RubyMotion 项目中使用 CoreMIDI。下面是一个简单的代码示例:

clientName = "Client"
clientRef = Pointer.new(:uint)
MIDIClientCreate( clientName, nil, nil, clientRef )

在以下要点中查看更详细的代码和回溯:https ://gist.github.com/4299810

该代码导致以下错误:

(主)> 2012-12-15 14:43:27.410 core-midi-test[42560:c07] app_delegate.rb:5:in application:didFinishLaunchingWithOptions:': expected instance of Pointer of type^{OpaqueMIDIClient}',得到I' (TypeError) 2012-12-15 14:43:27.412 core-midi-test[42560:c07] *** Terminating app due to uncaught exception 'TypeError', reason: 'app_delegate.rb:5:in应用程序:didFinishLaunchingWithOptions:':类型指针的预期实例^{OpaqueMIDIClient}', got我'(类型错误)'

该错误显然与 MIDIClientCreate 的第四个参数有关。MIDIClientCreate 的文档显示:

OSStatus MIDIClientCreate (
   CFStringRef     name,
   MIDINotifyProc  notifyProc,
   void            *notifyRefCon,
   MIDIClientRef   *outClient
);

MIDIClientRef 派生自定义为 UInt32 的 MIDIObjectRef,因此我相当确定 Pointer.new(:uint) 是与 RubyMotion 一起使用的正确类型。

以下是 RubyMotion 使用的 CoreMIDI.bridgesupport 文件的相关部分:

<function name='MIDIClientCreate'>
  <arg name='name' type='^{__CFString=}' declared_type='CFStringRef'/>
    <arg name='notifyProc' function_pointer='true' type='^?' declared_type='MIDINotifyProc'>
        <arg type='^{MIDINotification=iI}' declared_type='MIDINotification*' const='true'/>
        <arg type='^v' declared_type='void*'/>
        <retval type='v' declared_type='void'/>
    </arg>
    <arg name='notifyRefCon' type='^v' declared_type='void*'/>
    <arg name='outClient' type='^^{OpaqueMIDIClient}' declared_type='MIDIClientRef*'/>
    <retval type='l' declared_type='OSStatus'/>
</function>

据我所知,bridgesupport 定义应该包括必要的管道以进行正确的转换。但这当然是行不通的。

我的代码有问题还是 RubyMotion 包含的 CoreMIDI.bridgesupport 文件有问题?

4

1 回答 1

2

我通过阅读 MacRuby 的文档发现可以将所需的指针类型显式传递给 Pointer 构造函数,如下所示:

clientName = "Client"
clientRef = Pointer.new(MIDIClientRef.type)
MIDIClientCreate( clientName, nil, nil, clientRef )

portName = "Output"
outport = Pointer.new(MIDIPortRef.type)
MIDIOutputPortCreate( clientRef[0], portName, outport )
于 2012-12-16T05:36:43.127 回答