[#77789] [Ruby trunk Feature#12012] Add Boolean method — prodis@...
Issue #12012 has been updated by Fernando Hamasaki de Amorim.
4 messages
2016/10/27
[ruby-core:77538] ruby callback issue (no implicit conversion of nil into String)
From:
Luis C <luis.camp0.2009@...>
Date:
2016-10-10 12:43:44 UTC
List:
ruby-core #77538
Hi all,
The following code was working with swig 3.0 and with ruby < 2.3. So
probably the problem is on the ruby interpreter. However, because I just
swig to wrap the classes may be is something wrong on the definition or I
miss something. I got the error "no implicit conversion of nil into String
(TypeError)" from the callback parameter but if I access from a new
instance, works. This have been working in old versions of ruby. Any
similar problems?
File compile.sh
#!/bin/bash
swig -globalmodule -c++ -ruby ruby_wrapper.i
g++ -fPIC -std=c++11 -I/usr/include/ruby -c Callback.cc
ruby_wrapper_wrap.cxx
g++ -fPIC -shared -std=c++11 Callback.o ruby_wrapper_wrap.o -o example.so
-lruby
File Callback.h
#ifndef SRC_CALLBACK_H_
#define SRC_CALLBACK_H_
#include <iostream>
#include "MyClass.h"
#include <ruby.h>
class Callback
{
public:
Callback():callback_set_(false),callback_(Qnil),memory_wrapper_(Qnil),cc("another")
{
memory_wrapper_ = Data_Wrap_Struct(0 /* klass */, staticMark, NULL,
static_cast<void*>(this));
rb_gc_register_address(&memory_wrapper_);
}
virtual ~Callback() { rb_gc_unregister_address(&memory_wrapper_);}
bool haveCallback() const { return callback_set_;}
void setCallback(VALUE callback);
void executeCallback(MyClass *c);
void run();
protected:
static void staticMark(Callback *me) { me->mark(); }
void mark();
private:
bool callback_set_;
VALUE callback_;
VALUE memory_wrapper_;
MyClass cc;
};
#endif // SRC_CALLBACK_H_
File Callback.cc
#include "Callback.h"
void Callback::setCallback(VALUE callback) {
if (!NIL_P(callback)) {
// Verify the number of arguments of the callback by calling the
method arity
VALUE value = rb_funcall(callback,rb_intern("arity"),0);
int nargs = NUM2INT(value);
if (nargs != 1) {
rb_raise(rb_eRuntimeError,"Object should have one
parameter.\n");
}
callback_ = callback;
callback_set_ = true;
} else {
callback_ = Qnil;
callback_set_ = false;
}
}
void Callback::executeCallback(MyClass *c) {
if (!NIL_P(callback_)) {
ID id = rb_intern("MyClass");
if (rb_const_defined(rb_cObject, id)) {
VALUE rbClass = rb_const_get(rb_cObject,id);
VALUE rbData = Data_Wrap_Struct(rbClass, 0, 0, c);
rb_funcall(callback_,rb_intern("call"), 1, rbData);
}
}
}
void Callback::run() {
executeCallback(&cc);
}
void Callback::mark() {
if (!NIL_P(callback_)) {
rb_gc_mark(callback_);
}
}
File MyClass.h
#ifndef SRC_MYCLASS_H_
#define SRC_MYCLASS_H_
#include <iostream>
class MyClass
{
public:
MyClass():name_("default value"),value_(0) {}
MyClass(const std::string name): name_(name),value_(0) {}
virtual ~MyClass() {}
int getInt() { return value_; }
void setInt(int value) { value_ = value; }
const char *getName() const { return name_.c_str(); }
private:
std::string name_;
int value_;
};
#endif
File ruby_wrapper.i
%module(directors="1") example
%include <std_string.i>
%{
#include <iostream>
#include "Callback.h"
#include "MyClass.h"
using namespace std;
%}
%trackobjects;
%rename("my_name") MyClass::getName;
%rename("my_int") MyClass::getInt;
%rename("my_int=") MyClass::setInt;
%rename("callback=") Callback::setCallback;
%include "MyClass.h"
%include "Callback.h"
File test.rb
require './example'
def callback(cc)
print("From the callback")
print(cc.methods.sort)
print(cc.my_int)
print(cc.my_name)
end
puts "Testing example"
a = MyClass.new()
print("From the main")
print(a.methods.sort)
puts a.my_name
puts a.my_int
c = Callback.new()
c.callback = method(:callback)
c.run()
This code is working in ruby versions < 2.1, Any one have this problem?
other way to pass the c++ mapped object as parameter to the callback?
Thanks and regards,
Luis
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>