jasonroelofs/rbgccxml

Bug when handling function pointer arguments to methods

Closed this issue · 4 comments

I believe I found a bug in rbgccxml, concerning parsing methods that take function pointer attributes.

I found this when using rb++, but after some debugging am pretty sure that it has to do w/ the to_cpp operation (defined in lib/rgccxml/nodes/types/pointer_type.rb; invoked in lib/rbplusplus/builders/constructor.rb). Take the following rb++ code for example:

extconf.rb:

require 'rubygems'
require 'rbplusplus'
include RbPlusPlus

Extension.new "test" do |e| 
  e.sources "test.h"
  e.namespace "TestNamespace"
end

test.h:

#ifndef TESTNAMESPACE
#define TESTNAMESPACE

namespace TestNamespace {
  class Test{
     public:
       Test(void (*func)()) {}  
  };
}

#endif

Ran "ruby extconf.rb", "cd generated", "cp ../test.h .", make

Results in:

g++ -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -I/usr/include -I'/.../rb++/generated'   -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing  -fPIC   -Wall -g -c test.rb.cpp
g++ -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -I/usr/include -I'/.../rb++/generated'   -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing  -fPIC   -Wall -g -c _rbpp_custom.rb.cpp
g++ -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -I/usr/include -I'/.../rb++/generated'   -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing  -fPIC   -Wall -g -c _TestNamespace_Test.rb.cpp
_TestNamespace_Test.rb.cpp: In function ‘void register_TestNamespace_Test()’:
_TestNamespace_Test.rb.cpp:12: error: ‘*’ cannot appear in a constant-expression
_TestNamespace_Test.rb.cpp:12: error: template argument 2 is invalid
make: *** [_TestNamespace_Test.rb.o] Error 1

The c++ generated by rb++ which causes the error:

rb_cTest.define_constructor(Rice::Constructor< TestNamespace::Test,* >());

The gccxml generated constructor (output via a puts in rbgccxml)

<Constructor id="_161" name="Test" context="_154" access="public" mangled="_ZN13TestNamespace4TestC1EPFvvE *INTERNAL* " demangled="TestNamespace::Test::Test(void (*)())" location="f1:7" file="f1" line="7" inline="1">
<Argument name="func" type="_164" location="f1:7" file="f1" line="7"/>
</Constructor>

It seems when converting the pointer argument the pointer's data type doesn't get translated properly.

Not sure if this would be a tricky problem to solve in the greater context of rb++, eg what do you do when wrapping a C++ method that accepts a function pointer

Thanks again for all the great work

This is much more of an incomplete feature than a bug. Rb++ has preliminary support for methods that take callbacks, but I never thought to do the same with constructors (which, as I think about it, is not going to be easy right now).

As it stands, rb++ supports handling of methods that take a single function pointer parameter. Anything outside of this will generate invalid C++ code. This is probably something I should at least have rb++ error out before getting to the compilation phase.

If there's a bug here, it's having rbgccxml know how to properly #to_cpp a function pointer, otherwise it's more of a feature request for rb++.

You're right, I just verified that if I change the constructor in the example above to a regular method the code is generated / compiles fine (I can close this bug and open a feature request in rb++ if you want).

Was just curious why a constructor that takes function pointers would be more difficult to take care of than a regular method that does the same thing. You might be interested (as I see you maintain the ruby-ogre project) that this all arises when I try to generate ruby wrappers for CEGUI using rb++ which results in an error in the wrapper generated for /usr/include/CEGUI/CEGUIFreeFunctionSlot.h that takes a function pointer as the only constructor arg.

Rice's current setup is such that Rice::Constructor is very different from a normal method. When it comes to function pointers <=> ruby procs, there's no 1-1 mapping. Rb++ currently builds a wrapper function around the method in question which takes the VALUE parameter, saves it off for future use. Rb++ then generates another method to be used as the actual function pointer which can use the saved proc, do the required to/from ruby management, and otherwise hook everything up to be as seemless as possible (you can see this if you open up the generated code).

With methods and functions, this is easy. With Constructors this is much harder. Because we're dealing with C++ object instantiation, Rice handles these calls a bit differently, and it's not as simple as building a wrapper method to handle the func pointer <=> proc.

Of course, and idea comes to mind as I write this. I could possibly have rb++ generate an intermediary C++ class (much like Rice::Director) that takes a VALUE in the Constructor and can handle callbacks internally as needed.

The whole issue is hard to describe without knowing some of the internals of Rice, hopefully I've laid it out pretty well for you.

To keep things clean, we should probably close this ticket out, open one for rbgccxml and to_cpp of function pointers, and another on rb++ for Constructors that take function pointer(s?).

Thanks for the explanation, understand the gist of the issue now.

Will close this issue w/ this comment and open the two new ones now.