I don't know whether it has to do with the error you're getting, but I think
your create_project method is conceptually wrong, because if it should be
called from ruby, all arguments will be passed to it as VALUE s, not as char
or int or any other C type (this is because all ruby objects, on the C side
are of type VALUE).
Also, if you want to create a method which can be called with any number of
arguments from the ruby side, I think you should define it this way:
VALUE create_project(int argc, VALUE * argv, VALUE self)
{
}
extern "C" void Init_mytest(){
MyTest = rb_define_module("MyTest");
rb_define_method(MyTest, "create_project", &create_project, -1);
}
The argc parameter is the number of arguments passed to the method (and yes,
it's an exception to the rule I spoke of above about the arguments always
having to be of type VALUE). argv is an array of VALUEs representing the
arguments passed to the method and self is... self. To access the arguments of
the method, you iterate on argv:
for (int i = 0; i < argc; i++){
// do something with argv[i]
}
If some of the parameters of your method are required and some other optional,
you can use the rb_scan_args function, which manages them for you.
For more information, have a look at the chapter about extending ruby in the
pickaxe (for the free online edition, the chapter is at
Programming Ruby: The Pragmatic Programmer's Guide), at the
Doxygen documentation of the ruby C api and, in particular, to the section on
functions starting with the letter R
(http://www.ruby-doc.org/doxygen/current/globals_func.html#index_r\). This part
of the api contains a number of methods starting with rb_, which correspond
(more or less) directly to ruby methods. Unfortunately, there's no description
of the methods, but you can get an idea of what they do looking at their name.
Lastly, you can look at the source code of ruby itself (that's how I found the
information I gave you above). There are C files for the core classes
(array.c, object.c and so on). All the calls to rb_define_method are at the
end of the corresponding files, so you can quickly find out which C function
corresponds to which ruby method. You can download the ruby source code from
http://www.ruby-lang.org or browse the svn repository online at
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/tags/
I hope this helps
Stefano
···
On Thursday 10 July 2008, Mr_Tibs wrote:
Hi,
I wrote this question on the newsgroup yesterday, but I didn't see it
actually get posted. Here it goes again. I'm trying to call a c++
function from Ruby and I'm getting some errors compiling the c++
part.
Here is my code:
#include "ruby.h"
#include <iostream>
#include <stdarg.h>
VALUE MyTest = Qnil;
extern "C" VALUE create_project(char *c, ...)
{
va_list args;
va_start(args, c);
}
extern "C" void Init_mytest()
{
MyTest = rb_define_module("MyTest");
rb_define_method(MyTest, "create_project", &create_project,
1);
}
And here is the error:
MyTest.cpp: In function ‘void Init_mytest()’:
MyTest.cpp:16: error: invalid conversion from ‘VALUE (*)(char*, ...)’
to ‘VALUE (*)(...)’
MyTest.cpp:16: error: initializing argument 3 of ‘void
rb_define_method(VALUE, const char*, VALUE (*)(...), int)’
If I don't put "char *c" in the arguments of create_project, it
compiles and works just fine. But if I don't have it, how can I get
the arguments?
I realize this is more of a c++ question, but if anyone has any
simple, fully working example of calling c++ code from Ruby, I would
like to see it.
Thanks,
Tiberiu