2012-05-02 168 views
0

我一直用書實用的Ruby寶石。它給了我下面的代碼,我寫了:未定義的方法,MIDI

require 'dl/import' 
class LiveMIDI 
ON = 0x90 
OFF = 0x80 
PC = 0xC0 
    def initialize 
    open 
    end 
    def noteon(channel, note, velocity=64) 
    message(ON | channel, note, velocity) 
    end 
    def noteoff(channel, note, velocity=64) 
    message(OFF | channel, note, velocity) 
    end 
    def programchange(channel, preset) 
    message(PC | channel, preset) 
    end 
    module C 
    extend DL::Importer 
    dlload '/System/Library/Frameworks/CoreMIDI.framework/Versions/Current/CoreMIDI' 
    extern "int MIDIClientCreate(void *, void *, void *, void *)" 
    extern "int MIDIClientDispose(void *)" 
    extern "int MIDIGetNumberOfDestinations()" 
    extern "void * MIDIGetDestination(int)" 
    extern "int MIDIOutputPortCreate(void *, void *, void *)" 
    extern "void * MIDIPacketListInit(void *)" 
    extern "void * MIDIPacketListAdd(void *, int, void *, int, int, int, void *)" 
    extern "int MIDISend(void *, void *, void *)" 
    end 
    module CF 
    extend DL::Importer 
    dlload '/System/Library/Frameworks/CoreFoundation.framework/Versions/Current/CoreFoundation' 
    extern "void * CFStringCreateWithCString (void *, char *, int)" 
    end 
    def open 
    client_name = CF.CFStringCreateWithCString(nil, "RubyMIDI", 0) 
    @client = DL::PtrData.new(nil) 
    C.mIDIClientCreate(client_name, nil, nil, @client.ref); 

    port_name = CF.cFStringCreateWithCString(nil, "Output", 0) 
    @outport = DL::PtrData.new(nil) 
    C.mIDIOutputPortCreate(@client, port_name, @outport.ref); 

    num = C.mIDIGetNumberOfDestinations() 
    raise NoMIDIDestinations if num < 1 
    @destination = C.mIDIGetDestination(0) 
    end 

    def close 
    C.mIDIClientDispose(@client) 
    end 

    def message(*args) 
    format = "C" * args.size 
    bytes = args.pack(format).to_ptr 
    packet_list = DL.malloc(256) 
    packet_ptr = C.mIDIPacketListInit(packet_list) 
    # Pass in two 32 bit 0s for the 64 bit time 
    packet_ptr = C.mIDIPacketListAdd(packet_list, 256, packet_ptr, 0, 0, args.size, bytes) 
    C.mIDISend(@outport, @destination, packet_list) 
    end 
end 

當我嘗試運行它,我得到以下錯誤,我不明白,我從來沒有與DL:

工作過
livemidi.rb:36:in `open': undefined method `cFStringCreateWithCString' for LiveMIDI::CF:Module (NoMethodError) 
    from livemidi.rb:7:in `initialize' 
    from livemidi.rb:63:in `new' 
    from livemidi.rb:63:in `<main>' 

這是爲什麼??? 我正在使用Ruby 1.9.3,在Mac OS X上 你能幫我修復這個bug嗎?

+0

應該是顯而易見的,不存在所謂的'CFStringCreateWithCString'方法。 – 2012-05-02 23:34:34

回答

0

如果你搜索蘋果開發者文檔,你會發現一種稱爲CFStringCreateWithCStringCFStringCreateWithCString的方法簽名與您定義的方法簽名不同。正確的方法定義是。

CFStringRef CFStringCreateWithCString (
    CFAllocatorRef alloc, 
    const char *cStr, 
    CFStringEncoding encoding 
); 

這意味着你應該改變。

extern "void * CFStringCreateWithCString (void *, char *, int)" 

到。

extern "CFStringRef CFStringCreateWithCString(CFAllocatorRef, const char*, CFStringEncoding)" 
0

你的麻煩似乎是你打電話cFStringCreateWithCString,但功能被稱爲CFStringCreateWithCString - 資本是非常重要的。

+0

雖然第36行確實調用了'CFStringCreateWithCString'。 – 2012-05-03 01:40:36

+0

@dunsmoreb:錯誤清楚地顯示小寫版本,所以他必須粘貼不同版本的代碼,而不是錯誤來自。大寫版本確實存在 - 我已經運行了代碼並確認了這一點。 – Chuck