2015-03-02 15 views
1

比方说,我有一个C/C++库使用此函数,编译为一个DLL:红宝石 - 传递方法的DLL库作为回调

#include <Windows.h> 

extern "C" __declspec(dllexport) void __stdcall myFunction(void (*myCallback)(int)) { 
    int result = MessageBox(
     0, (LPCWSTR)L"Press yes or no", (LPCWSTR)L"Test", MB_YESNO 
    ); 
    myCallback(result); 
} 

它只是打开标准的Win32消息框,并传递导致回调函数。

问题是:是否可以在Ruby中使用此函数,通过Fiddle或类似的东西,并将Ruby方法以某种方式传递给它,以便从C++代码中调用它?

这里是我用来导入DLL库的Ruby代码:

require "fiddle" 

myLibrary = Fiddle.dlopen("myLibrary.dll") 
myFunction = Fiddle::Function.new(
    myLibrary["myFunction"], 
    [Fiddle::TYPE_VOIDP], 
    Fiddle::TYPE_VOID 
) 

def myCallback(value) 
    puts "MessageBox result is #{value}" 
end 

而这显然是行不通的:

myFunction.call(method(:myCallback)) 

它只是抛出一个TypeError - 不能转换方法整数。

有没有办法将回调传递给C函数?

+0

可能相关:http://stackoverflow.com/questions/3327666/win32s-findwindow-can-find-a-particular-window-with-the-exact-title-but-what该链接描述如何使用Ruby调用需要回调的API函数。所以你可以用它作为指导。 – PaulMcKenzie 2015-03-02 21:20:01

+1

测试包括['qsort()'示例](https://github.com/ruby/ruby/blob/ae048b1b7c0b1e632d97c448518932dc53f8cae6/test/fiddle/test_func.rb#L72-L90)。另外请看'Fiddle :: Importer#bind'。 – cremno 2015-03-02 21:45:20

+0

谢谢你的qsort()例子!小提琴::闭合似乎是正确的回调:) – 2015-03-02 22:00:20

回答

0

所以我找到了解决办法:

myClosure = Class.new(Fiddle::Closure) { 
    def call(value) 
    puts "MessageBox result is #{value}" 
    end 
}.new(Fiddle::TYPE_VOID, [Fiddle::TYPE_INT]) 

然后,我可以简单地调用C函数:

myFunction.call(myClosure) 

我真的不知道这是如何工作 - 但它工作正常。