From: Stefano Crocco Date: 2008-07-11T02:03:33+09:00 Subject: Re: calling c++ from Ruby 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 > #include > 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 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 http://www.ruby-doc.org/docs/ProgrammingRuby/html/ext_ruby.html), 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