gpt4 book ai didi

c++ - 使用 Rice : How to transmit the pointer of Ruby method (callback) to C++ function? 在 C++ 中构建 Ruby 扩展

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:55:58 25 4
gpt4 key购买 nike

我有一个非常酷的 C++ 库,名为 libcage .我需要库中类的方法才能从 Ruby 脚本调用。 我正在使用 Rice 在 C++ 中构建 Ruby 扩展.

cage 类中的join 方法使用参数作为指向回调函数的指针。简化说明性示例使用 C++ 中的回调:

/* File example.cpp */
#include <libcage/cage.hpp>

void joinCallback(bool joinResult) {
// do something
}
int main(int argc, char *argv[]) {
libcage::cage *cage = new libcage::cage;
cage->join("localhost", 80, &joinCallback);
}
/* End of file example.cpp */

在某些事件发生后,join 方法将调用callback 函数。这没问题,但是我想要在 Ruby 中定义回调函数!

# File example.rb
require './rb_libcage' # C++ extension library

def joinCallback(joinResult)
# do something
end

cage = Cage.new
cage.join "localhost", 80, method(:joinCallback)
# End of file example.rb

现在这行不通了。 我不知道如何通过下面示例中的调用参数 callback_to_ruby 将 Ruby 方法的指针传递给 C++ 函数


编辑:

我实际上现在有这个:

/* File rb_libcage.cpp */
#include "rice/Class.hpp"
#include "rice/Data_Type.hpp"
#include "rice/Constructor.hpp"

#include "cage.hpp"

Rice::Object __callback_to_ruby;
ID __callback_id_to_ruby;

namespace {
void c_callback(bool result)
{
if (result)
std::cout << "join: succeeded" << std::endl;
else
std::cout << "join: failed" << std::endl;

/* This does not work! */
__callback_to_ruby.call(__callback_id_to_ruby,"AsyncCallback");
/**
* terminate called after throwing an instance of 'Rice::Exception'
* what(): undefined method `call' for "AsyncCallback":String
* Aborted
*/
}
class Cage_wrapper
{
public:
Cage_wrapper() : cage(new libcage::cage()) {}

void join(std::string host, int port, Rice::Object callback_to_ruby) {
__callback_to_ruby = callback_to_ruby;
__callback_id_to_ruby = rb_intern("call");
__callback_to_ruby.call(__callback_id_to_ruby,"test"); /* This works! */

/* cage->join() will make another thread that will call ASYNCHRONOUSLY c_callback function */
cage->join(host, port, &c_callback);
}
private:
libcage::cage *cage;
};

extern "C"
void Init_rb_libcage(void)
{
RUBY_TRY
{
Rice::define_class<Cage_wrapper>("Cage")
.define_constructor(Rice::Constructor<Cage_wrapper>())
.define_method("join", &Cage_wrapper::join);
}
RUBY_CATCH
}
} // namespace
/* End of file rb_libcage.cpp */

和 Ruby 脚本:

# File example.rb
require './rb_libcage' # C++ extension library

ruby_callback = lambda {|x| print "From ruby script join result: ", x, "\n" }
cage = Cage.new
cage.join "localhost", 80, ruby_callback
puts 'After join'
# End of file example.rb

rb_libcage.cpp 是可编译的,运行 example.rb 如下所示:

From ruby script join result: test
After join
join: succeeded
terminate called after throwing an instance of 'Rice::Exception'
what(): undefined method `call' for "AsyncCallback":String
Aborted

我可以调用同步回调,但不能调用异步回调。它会丢失上下文吗? C++代码如何异步调用ruby回调成功?

最好的问候,帕维尔

P.S.:我发现有用 article about building Asynchronous callbacks in Ruby C extensions

最佳答案

我不是 ruby​​ 专家,但我认为 Cage_wrapper.join 方法签名可能希望看起来更像

void join(std::string host, int port, Rice::Object *ruby_proc)

您可以使用 ruby​​ proc 作为对 native 库的回调。即 Rice::Object 是 ruby​​ 过程。

然后在某个时候你会想要做一个 ruby​​_proc.call()。因此,您可能需要将对 ruby​​_proc.call 的调用包装在回调中,这对 native cage join 来说是可以接受的。

关于c++ - 使用 Rice : How to transmit the pointer of Ruby method (callback) to C++ function? 在 C++ 中构建 Ruby 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19014103/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com