Ruby FFI 帮助

发布于 2024-10-11 09:59:53 字数 1176 浏览 3 评论 0原文

我只是尝试进行一些基本的 Windows 调用来打印来自 MIDI 输入设备(键盘)的信息。这些调用似乎有效,但对 midiInOpen 和 midiInStart 的前两次调用返回 MMSYSERR_NOMEMMMSYSERR_INVALHANDLE。我相信它与 ptr = FFI::MemoryPointer.new(:pointer) 有关,但我对 FFI 的了解不够,无法弄清楚。任何帮助表示赞赏。

require 'ffi'

module MIDI; end

module MIDI::Input
  extend FFI::Library

  ffi_lib 'winmm'
  ffi_convention :stdcall

  callback :midiInProc, [ :pointer, :uint, :int, :int, :int  ], :void

  attach_function :midiInOpen, [ :pointer, :uint, :midiInProc, :int, :int ], :int
  attach_function :midiInClose, [ :long ], :int

  attach_function :midiInStart, [ :long ], :int
  attach_function :midiInStop, [ :long ], :int
  attach_function :midiInReset, [ :long ], :int

  MidiInProcCallback = Proc.new do |hmidiin, wmsg, dwintance, dwparam1, dwparam2|
    p hmidiin, wmsg, dwintance, dwparam1, dwparam2
  end
end

require 'pp'
ptr = FFI::MemoryPointer.new(:pointer)
p MIDI::Input.midiInOpen(ptr, 0, MIDI::Input::MidiInProcCallback, 0, 0)
p MIDI::Input.midiInStart(ptr.read_long)

trap("INT") do
  p MIDI::Input.midiInStart(ptr.read_long)
  p MIDI::Input.midiInClose(ptr.read_long)
  p ptr.free
  exit
end

loop {}

I am simply trying to make a few basic Windows calls to print the information from a MIDI input device (keyboard). The calls seem to work, but the first two calls to midiInOpen and midiInStart return MMSYSERR_NOMEM and MMSYSERR_INVALHANDLE. I believe it has something to do with ptr = FFI::MemoryPointer.new(:pointer) but I don't know enough about FFI to figure it out. Any help is appreciated.

require 'ffi'

module MIDI; end

module MIDI::Input
  extend FFI::Library

  ffi_lib 'winmm'
  ffi_convention :stdcall

  callback :midiInProc, [ :pointer, :uint, :int, :int, :int  ], :void

  attach_function :midiInOpen, [ :pointer, :uint, :midiInProc, :int, :int ], :int
  attach_function :midiInClose, [ :long ], :int

  attach_function :midiInStart, [ :long ], :int
  attach_function :midiInStop, [ :long ], :int
  attach_function :midiInReset, [ :long ], :int

  MidiInProcCallback = Proc.new do |hmidiin, wmsg, dwintance, dwparam1, dwparam2|
    p hmidiin, wmsg, dwintance, dwparam1, dwparam2
  end
end

require 'pp'
ptr = FFI::MemoryPointer.new(:pointer)
p MIDI::Input.midiInOpen(ptr, 0, MIDI::Input::MidiInProcCallback, 0, 0)
p MIDI::Input.midiInStart(ptr.read_long)

trap("INT") do
  p MIDI::Input.midiInStart(ptr.read_long)
  p MIDI::Input.midiInClose(ptr.read_long)
  p ptr.free
  exit
end

loop {}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

高冷爸爸 2024-10-18 09:59:53

没有明确的答案,因为您的代码看起来大部分是正确的,但我怀疑您传递给 midiInOpen() 的 dwFlags (最后一个参数)才是问题所在。查看 http://msdn.microsoft.com /en-us/library/dd798458(v=vs.85).aspx,似乎它需要非零。

尝试在 winmm 头文件中查找 CALLBACK_FUNCTION 的值,并在模块中声明一个类似的常量,然后将其用作标志参数。

http://powersdr-iq.googlecode 有一个 C# 包装器.com/svn/trunk/Source/Console/midi.cs 这可能是其他人使用 C# P/Invoke 接口包装相同 API 的有用示例。

您的 midiInOpen 签名和回调略有错误(但不会导致此问题)。它们应该是:

callback :midiInProc, [ :pointer, :uint, :pointer, :pointer, :pointer  ], :void

attach_function :midiInOpen, [ :pointer, :uint, :midiInProc, :pointer, :int ], :int

即使用 :pointer,其中 API 文档使用 DWORD_PTR

No definite answer, as your code looks mostly correct, but I suspect it is the dwFlags (the last param) you are passing to midiInOpen() that is the problem. Looking at http://msdn.microsoft.com/en-us/library/dd798458(v=vs.85).aspx, it seems that it needs to be non-zero.

Try looking in the winmm header file for the value of CALLBACK_FUNCTION, and declare a similar constant in your module, then use it as the flags param.

There is a C# wrapper at http://powersdr-iq.googlecode.com/svn/trunk/Source/Console/midi.cs that might be useful example of someone else wrapping the same API using the C# P/Invoke interface.

Your signatures for midiInOpen and the callback are slightly wrong (but won't be causing this problem). They should be:

callback :midiInProc, [ :pointer, :uint, :pointer, :pointer, :pointer  ], :void

attach_function :midiInOpen, [ :pointer, :uint, :midiInProc, :pointer, :int ], :int

i.e. use :pointer where the API docs use DWORD_PTR

冰葑 2024-10-18 09:59:53

看看 https://github。 com/arirusso/midi-winmm/blob/master/lib/midi-winmm/map.rb

哦!那是你的一些。凉爽的。有用。

我知道这在 Windows 中有效,因为我已经尝试过了。我最大的愿望是找到 Microsoft 的 winmm.dll api 文档。我想我已经找到了,感谢 user186057 回答了你的问题。

谢谢。

Have a look at https://github.com/arirusso/midi-winmm/blob/master/lib/midi-winmm/map.rb

Oh! That is some of yours. Cool. It works.

I know this works in windows because I've tried it out. My biggest desire is to find the documentation from Microsoft for the winmm.dll api. which I think that I have found thanks to your question being answered by user186057.

Thanks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文