Giter Site home page Giter Site logo

jasonroelofs / rbplusplus Goto Github PK

View Code? Open in Web Editor NEW
60.0 5.0 6.0 910 KB

Use rbgccxml and rice to automatically generate Ruby extensions around C++ source and libraries.

License: MIT License

Ruby 81.78% C++ 12.62% Objective-C 0.25% C 0.24% CSS 4.00% HTML 1.11%

rbplusplus's Introduction

What is rb++?

Rb++ lets you create Ruby extensions for any C++ library. In the simplest of cases, there is no need to ever touch C++, everything is done in Ruby.

For wrapping plain C libraries, I highly recommend FFI: http://github.com/ffi/ffi

Note: For those familiar with py++, the similarities are minimal. Outside of the purpose of both libraries, rb++ was built from scratch to provide a Ruby-esque query and wrapping API instead of being a port. However, many thanks to Roman for his work, the major inspiration for this library.

Requirements

Installation

Rice builds and installs on any *nix system, including Mac OS X. Rice and rb++ have been shown to work under Cygwin and MinGW / MSYS.

gem install rbplusplus

The Project

Rb++'s source is in a git repository hosted on github:

http://github.com/jasonroelofs/rbgplusplus/tree/master

Clone with:

git clone git://github.com/jasonroelofs/rbplusplus.git

Getting Started

All rb++ projects start off with the Extension class:

require 'rbplusplus'
include RbPlusPlus

Extension.new "extension_name"

Rb++ has one requirement on the C++ code: it must be wrapped in a namespace. If the code you're trying to wrap is not in it's own namespace, please build a seperate header file that wraps everything in a namespace as such:

namespace to_wrap {
  #include "file1.h"
  #include "file2.h"
  #include "file3.h"
  ...
}

Extension has two ways of being used: block syntax for simple projects and immediate syntax for more control over the whole process.

Block Mode

For most extension wrapping needs, Block Mode takes care of automating everything that it can:

Extension.new "extension" do |e|
  ...
end

Immediate Mode

For those that want more fine-grained control over the parsing / building / writing / compiling process, immediate syntax is also available

e = Extension.new "extension"
...
e.build    # => Generates the C++ code
e.write    # => Writes out to files
e.compile  # => Compiles the extension

Please note the #build, #write, and #compile methods. These are required for an extension to be built and must be called in this order. These calls are made automatically in Block Mode. See the RbPlusPlus::Extension class for more details.

Basic Usage

For the most basic usage, there are only two required calls: Extension.sources and Extension.namespace. Extension.sources has a few ways to be called (which takes most the same parameters as RbGCCXML.parse):

# A single header file
Extension.new "extension" do |e|
  e.sources "/path/to/header.h"
end

# An array of header files
Extension.new "extension" do |e|
  e.sources ["/path/to/header.h", "/path/there.h"]
end

# A glob
Extension.new "extension" do |e|
  e.sources "/path/to/*.h"
end

# An array of globs
Extension.new "extension" do |e|
  e.sources ["/path/to/*.h", "/elsewhere/*.hpp"]
end

Once your sources are defined, you need to tell rb++ the name of the namespace from which code needs to be wrapped. This is done using the #namespace method in one of two different situations:

# Wrap all code under the 'to_wrap' namespace
Extension.new "extension" do |e|
  e.namespace "to_wrap"
end

When wrapping code under ruby modules, you specify which namespace should be wrapped into which module as so:

# Wrap all code under the 'to_wrap' namespace
Extension.new "extension" do |e|
  e.module "ExtMod" do |m|
    m.namespace "to_wrap"
  end

  e.module "Util" do |m|
    m.namespace "to_wrap_util"
  end
end

The general rule is this: If you want C++ code wrapped, you must use Extension#namespace to specify where your C++ code will get wrapped.

When working in Immediate Mode, there is one more required method after #sources and #namespace: #working_dir=, which you use to specify which directory to write out the Rice source code. When using Block Mode, rb++ can figure out a good default working directory due to __FILE__ on the block's binding. Without this block, rb++ is clueless and must be told where it's working directory should be:

e = Extension.new "extension"
e.working_dir = "/path/to/generate/files/"

More Detailed Usage

Because C++ does not easily wrap into Ruby code for many reasons, rb++ is much more capable than just the basic usage above. There are many different features available to help define and build the wrapper.

Modules

An extension can include modules in which code will be wrapped. Any given module needs to either be given a #namespace call or be directly given code nodes to wrap using Module#includes. This specifies which C++ code will be wrapped into this module.

Extension.new "extension" do |e|
  e.sources ...
  # If there is no global-space code to be wrapped
  # #namespace is not required here

  e.module "MyModule" do |m|
    # We want to wrap all code in ::my_module into this ruby module
    m.namespace "my_module"
  end
end

Particularly hairy APIs

It's well known that source code may not follow a very clean format, or even be internally consistent. When dealing with such problems -- code that just won't adhere to a wrappable format -- rb++ opens up a slew of manipulation routines for controlling exactly what gets wrapped, where it gets wrapped, and how it gets wrapped.

Ignoring

Often times you will want to ignore a method on an object, a whole class, or a whole namespace even. This can be useful if the function you wish to ignore takes a 'void *' as an argument, or for a variety of other reasons.

You can tell rb++ which namespaces/classes/methods to ignore with #ignore:

Extension.new "extension" do |e|
  e.sources ...
  node = e.namespace "Physics"
  node.classes("Callback").ignore                           # Ignore classes named Callback
  node.classes("Shape").methods("registerCallback").ignore  # Ignore the method Shape::registerCallback
end

You can also ignore a whole set of query results with the same notation:

Extension.new "extension" do |e|
  ...
  node.methods.find(:all, :name => "free").ignore           # Ignores all instance methods named 'free'
  ...
end

Including

For more control over exactly where a given piece of C++ code will be wrapped, use Module#includes:

Extension.new "extension" do |e|
  e.sources ...
  node = e.namespace "PhysicsMath"

  e.module "Physics" do |m|
    m.module "Math" do |math|
      # Moves each class in ::PhysicsMath to Physics::Math.
      # Not the best example but gets the point across. The proper
      # way to do this is to do math.namespace "PhysicsMath" here
      node.classes.each do |c|
        math.includes c
      end
    end
  end

end

Note that when you include something in a module it is moved from it's original location. In the example above the classes will only exist in Physics::Math and will no longer show up in the global space.

Renaming

Sometimes C++ libraries implement certain architectures that are nice to have in C++, but are terrible in Ruby, or standards in Ruby aren't possible in C++ (func?, func=, func!). For this reason, every node can be renamed using the #wrap_as method:

Extension.new "extension" do |e|
  e.sources ...
  node = e.namespace "Physics"
  node.classes("CShape").wrap_as("Shape")
  node.classes("CShape").methods("hasCollided").wrap_as("collided?")
end

Note: rb++ automatically underscores all method names and CamelCases all class names that haven't been otherwise changed with #wrap_as.

Function / Method Conversions

C++ APIs can also sometimes expose global functionality you want contained in a class or module. This kind of wrapping is also possible in rb++. Say you have the function:

inline int mod(int a, int b) {
  return a%b;
}

and you want to add it to your Math class as an instance method. Use #as_instance_method and #includes:

mod = node.functions("mod")
node.classes("Math").includes mod.as_instance_method

----

require 'extension'

Math.new.mod(1, 2)

Possible 'Gotchas'

Constructor overloading

A current limitation in rice currently does not allow for more than one constructor to be exported. This will not be a limitation in future versions of Rice, but for now make sure that only one constructor is wrapped. This can be done via direct constructor access:

node.classes("MyClass").constructors[0].ignore

or by querying according to the arguments of the constructor(s) you want to ignore:

node.classes("MyClass").constructors.find(:arguments => [nil,  nil]) # ignore constructors with 2 arguments

Contrary to ignoring a constructor, you can also expliclty tell rb++ which constructor to use:

my_class = node.classes("MyClass")
my_class.use_constructor my_class.constructors[0]

Rb++ will print out a (WARNING) for each class affected by this.

Method overloading

Method overloading not currently supported in Rice, thus rb++ has a workaround built in. All overloaded methods are wrapped in the order that they are presented to gccxml. For example:

class System {
  public:
  System() {}
  inline void puts(std::string s) { std::cout << s << std::endl; }
  inline void puts() { puts(""); }
};

Will be exposed by default like so:

s = System.new
s.puts_0("Hello world")
s.puts_1

You can, however, rename them as you see fit if you tell rb++ how, for example:

puts_methods = node.classes("System").methods("puts")
puts_methods[0].wrap_as("puts")

After doing this you can use the methods as follows:

s = System.new
s.puts("Hello World")
s.puts_1

As of right now, there isn't a specific way to say "use this method as the default name", you need to make sure you use #wrap_as on the method you want to stay the same and let the others get the suffix.

Misc Options

File Writing Options

By default, rb++ will write out the extension in multiple files, following the convention of

extension_name.rb.cpp
__ClassName.rb.hpp
__ClassName.rb.cpp
__ModuleName_ClassName.rb.hpp
__ModuleName_ClassName.rb.cpp
...

This is done to prevent obscenely long compile times, super large code files, or uncompilable extensions due to system limitations (e.g. RAM) that are common problems with big SWIG projects. Rb++ can also write out the extension code in a single file (extension_name.cpp) with Extension#writer_mode

Extension.new "extension" do |e|
  e.writer_mode :single # :multiple is the default
end

Compilation options

Rb++ takes care of setting up the extension to be properly compiled, but sometimes certain compiler options can't be deduced. Rb++ has options to specify library paths (-L), libraries (-l), and include paths (-I) to add to the compilation lines, as well as just adding your own flags directly to the command line. These are options on Extension.sources

Extension.new "extension" do |e|
  e.sources *header_dirs,
    :library_paths => *paths,       # Adds to -L
    :libraries => *libs,            # Adds to -l
    :include_paths => *includes,    # Adds to -I
    :cxxflags => *flags,            # For those flags that don't match the above three
    :ldflags => *flags,             # For extra linking flags that don't match the above
    :includes => *files,            # For when there are header files that need to be included into the
                                    #   compilation but *don't* get parsed and wrapped
    :include_source_files => *files # A list of source files that will get copied into working_dir and
                                    #   compiled with the extension
    :include_source_dir => dir      # Specify a directory. Rb++ will build up a list of :includes and
                                    #   :include_source_files based on the files in this directory
end

Command Line Arguments

Rb++ exposes a few command line arguments to your wrapper script that allow more find-grained control over running your script. These options are:

Usage: ruby build_noise.rb [options]
  -h, --help                       Show this help message
  -v, --verbose                    Show all progress messages (INFO, DEBUG, WARNING, ERROR)
  -q, --quiet                      Only show WARNING and ERROR messages
      --console                    Open up a console to query the source via rbgccxml
      --clean                      Force a complete clean and rebuild of this extension

Logging

All logging is simply sent straight to STDOUT except (ERROR) messages which are sent to STDERR.

Compilation logs are found in [working_dir]/rbpp_compile.log.

rbplusplus's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

rbplusplus's Issues

File name too long error

I'm getting this trying to compile ogrerb:

/usr/lib64/ruby/gems/1.8/gems/rbplusplus-0.9.1/lib/rbplusplus/writers/multiple_files_writer.rb:210:in `initialize': File name too long - /home/yo/tmp/ogrerb/ogrerb/generated/ogre/.build/Ogre_multimap_Ogre_HardwareVertexBufferPtr__Ogre_HardwareVertexBufferSharedPtr__std_less_Ogre_HardwareVertexBufferPtr___Ogre_STLAllocator_std_pair_Ogre_HardwareVertexBufferPtr_const__Ogre_HardwareVertexBufferSharedPtr___Ogre_CategorisedAllocPolicy.rb.hpp (Errno::ENAMETOOLONG)

I'm using linux with an ext3 partition, which allows only 256 bytes for the file name.

Support for function pointers arguments to constructors

This is the second of two issues stemming from this original bug report: http://github.com/jameskilton/rbgccxml/issues#issue/4

It seems that currently function pointers are not allowed to be passed to a class constructor in the same manner as how they are passed to regular (non-constructor) methods.

Trying to parse C++ code that passes a function pointer to a constructor w/ rb++ results in invalid output code, the function pointer argument not being generated properly in the resulting wrapper code.

See the aforementioned issue (http://github.com/jameskilton/rbgccxml/issues#issue/4) for a code example demonstrating this problem.

:include_source_file does not add needed headers to all source files

I tried to create my custom wrappers. This worked for me in simple cases (where only one cpp file is generated), but not in more complicated cases. The main problem seems to be that the header file should be included in all wrapper files (that wrap different classes), but this isn't the case.

I tried to debug this, and apparently the settings are not send to different ClassNodes and thus the files are not included in the generated .rb.cpp files.

The same problem exists for :includes, which is documented as: "Header file(s) to include at the beginning of each .rb.cpp file generated.", but are actually only included in the ExtensionNode's source file.

typedef in namespace not recognized.

Hi,

I am having a problem compiling a rbplusplus wrapper for a c++ project which involves two namespaces, lm and lm::ngram. This is the rb++ file:

require 'rbplusplus'
require 'fileutils'
include RbPlusPlus

KENLM_DIR = File.expand_path(File.dirname(__FILE__))

Extension.new "kenlm" do |e|
  e.working_dir = File.join(KENLM_DIR, "generated")
  e.sources [ "lm/model.hh" ],
    :include_paths => KENLM_DIR,
    :include_source_dir => File.join(KENLM_DIR, "lm"),
    :include_source_dir => File.join(KENLM_DIR, "util")

  e.module "Kenlm" do |m|
    node = m.namespace "lm"

    m.module "Ngram" do |ngram|
      node = ngram.namespace "ngram"

#      node.classes("TrieModel").use_constructor(
#   node.classes("TrieModel").constructors.find(:arguments => [nil])
#      )
      #node.classes("TrieModel").methods("Score").find(:arguments => [nil, nil, nil])[0].ignore
    end
  end
end

I have created a repo at https://github.com/kpm/kenlm-rb in case you wanted to browse any files. Again, I'm not sure if this is an issue with rb++ itself or the c++ project itself.

This is the version of the gem:
% gem dep rbplusplus
Gem rbplusplus-1.0.1
rbgccxml (> 1.0, runtime)
rice (
> 1.4.0, runtime)

Here is the rbpp_compile.log:

checking for main() in -lrice... yes
creating Makefile
g++ -I. -I/usr/include/ruby-1.9.1/x86_64-linux -I/usr/include/ruby-1.9.1/ruby/backward -I/usr/include/ruby-1.9.1 -I.    -I/var/lib/gems/1.9.1/gems/rice-1.4.3/ruby/lib/include -I'/home/kmeyer/dev/kenlm/generated' -I/home/kmeyer/dev/kenlm  -fPIC -fno-strict-aliasing -g -g -O2 -fPIC   -Wall -g -o exception.o -c exception.cc
g++ -I. -I/usr/include/ruby-1.9.1/x86_64-linux -I/usr/include/ruby-1.9.1/ruby/backward -I/usr/include/ruby-1.9.1 -I.    -I/var/lib/gems/1.9.1/gems/rice-1.4.3/ruby/lib/include -I'/home/kmeyer/dev/kenlm/generated' -I/home/kmeyer/dev/kenlm  -fPIC -fno-strict-aliasing -g -g -O2 -fPIC   -Wall -g -o _rbpp_custom.rb.o -c _rbpp_custom.rb.cpp
g++ -I. -I/usr/include/ruby-1.9.1/x86_64-linux -I/usr/include/ruby-1.9.1/ruby/backward -I/usr/include/ruby-1.9.1 -I.    -I/var/lib/gems/1.9.1/gems/rice-1.4.3/ruby/lib/include -I'/home/kmeyer/dev/kenlm/generated' -I/home/kmeyer/dev/kenlm  -fPIC -fno-strict-aliasing -g -g -O2 -fPIC   -Wall -g -o _lm_ConfigException.rb.o -c _lm_ConfigException.rb.cpp
g++ -I. -I/usr/include/ruby-1.9.1/x86_64-linux -I/usr/include/ruby-1.9.1/ruby/backward -I/usr/include/ruby-1.9.1 -I.    -I/var/lib/gems/1.9.1/gems/rice-1.4.3/ruby/lib/include -I'/home/kmeyer/dev/kenlm/generated' -I/home/kmeyer/dev/kenlm  -fPIC -fno-strict-aliasing -g -g -O2 -fPIC   -Wall -g -o _lm_LoadException.rb.o -c _lm_LoadException.rb.cpp
g++ -I. -I/usr/include/ruby-1.9.1/x86_64-linux -I/usr/include/ruby-1.9.1/ruby/backward -I/usr/include/ruby-1.9.1 -I.    -I/var/lib/gems/1.9.1/gems/rice-1.4.3/ruby/lib/include -I'/home/kmeyer/dev/kenlm/generated' -I/home/kmeyer/dev/kenlm  -fPIC -fno-strict-aliasing -g -g -O2 -fPIC   -Wall -g -o _lm_ngram_State.rb.o -c _lm_ngram_State.rb.cpp
_lm_ngram_State.rb.cpp:11:77: error: expected ‘,’ or ‘...’ before ‘val’
_lm_ngram_State.rb.cpp: In function ‘void wrap_lm_ngram_State_words_set(lm::ngram::State*, lm::WordIndex*)’:
_lm_ngram_State.rb.cpp:12:16: error: ‘val’ was not declared in this scope
_lm_ngram_State.rb.cpp: At global scope:
_lm_ngram_State.rb.cpp:14:14: error: expected unqualified-id before ‘[’ token
_lm_ngram_State.rb.cpp:17:71: error: expected ‘,’ or ‘...’ before ‘val’
_lm_ngram_State.rb.cpp: In function ‘void wrap_lm_ngram_State_backoff_set(lm::ngram::State*, float*)’:
_lm_ngram_State.rb.cpp:18:18: error: ‘val’ was not declared in this scope
_lm_ngram_State.rb.cpp: At global scope:
_lm_ngram_State.rb.cpp:20:6: error: expected unqualified-id before ‘[’ token
_lm_ngram_State.rb.cpp: In function ‘void register_lm_ngram_State(Rice::Module)’:
_lm_ngram_State.rb.cpp:34:36: error: ‘wrap_lm_ngram_State_words_get’ was not declared in this scope
_lm_ngram_State.rb.cpp:36:38: error: ‘wrap_lm_ngram_State_backoff_get’ was not declared in this scope
make: *** [_lm_ngram_State.rb.o] Error 1

Thanks.

Finders aren't acting the same

In Ogre.rb, noticed that:

ogre.classes(/SharedPtr/)

returns an Array while

ogre.classes.find(:name => /SharedPtr/)

properly returns a QueryResult.

Segfault using callbacks and GC

I run into a problem on a ruby extension I'm working on and tried to track it down. So here is a minimal example which segfaults:

C++ class:

#include <string>
#include <iostream>

namespace RbRiceTest {

  typedef void (*RubyCallback) ();

  class MyClass
  {
  public:
    MyClass  () { }    
    ~MyClass () { }

    void onSomeEvent (RubyCallback callback) {
      onSomeEventCallback = callback;
    }

    void initiateCallback ()      
    {        
      std::cout << "C: before calling callback" << std::endl;
      onSomeEventCallback ();
      std::cout << "C: after calling callback" << std::endl;
    }

  private:
    RubyCallback onSomeEventCallback;

  };

}

Ruby test;

#!/usr/bin/env ruby

require_relative 'ricetest/ricetest.so'

obj = RiceTest::MyClass.new

obj.on_some_event do
  puts 'R: callback called'
end 

puts 'R: before initiate_callback'
obj.initiate_callback
puts 'R: after initiate_callback'

# simulate an arbitrary GC run
GC.start
puts 'R: garbage collected'

puts 'second try (which will fail!)'
puts 'R: before initiate_callback'
obj.initiate_callback
puts 'R: after initiate_callback'

Build script:

#!/usr/bin/env ruby

require 'rbplusplus'

base_path = File.expand_path File.dirname(__FILE__) + '/src'

RbPlusPlus::Extension.new 'ricetest' do |ext|
  ext.working_dir = base_path + '/../ricetest'
  ext.sources [base_path + '/my_class.h']
  ext.module 'RiceTest' do |mod|
    node = mod.namespace 'RbRiceTest'
    server = node.classes('MyClass')
    server.use_constructor server.constructors[1]
  end
end

The second obj.initiate_callback will result in a segfault. But I have no idea why. It will not crash if I remove the GC.start call (but I suspect it would at the time ruby calls the GC). And it will not crash if I remove the std::cout lines in the C++ code...

Am I implementing callbacks wrongly? Or is this a bug?

Im using rb++ 1.2.0 and rice 1.6.0 on ruby 2.1.1p72. I tried on older versions of Ruby, same problem there.

Anyone an idea?

Thanks
Andy

Problem with XML parsing

Hi,
I'm just trying to use rbplusplus to wrap Player/Stage C++ interface, and I stumbled upon this:

(INFO) Parsing ["/usr/include/player-3.0/libplayerc++/playerc++.h"]
/home/v01d/.gem/ruby/1.9.1/gems/rbgccxml-1.0/lib/rbgccxml/sax_parser.rb:38:in []': odd number of arguments for Hash (ArgumentError) from /home/v01d/.gem/ruby/1.9.1/gems/rbgccxml-1.0/lib/rbgccxml/sax_parser.rb:38:instart_element'
from /home/v01d/.gem/ruby/1.9.1/gems/nokogiri-1.4.4/lib/nokogiri/xml/sax/document.rb:116:in start_element_namespace' from /home/v01d/.gem/ruby/1.9.1/gems/nokogiri-1.4.4/lib/nokogiri/xml/sax/parser.rb:93:inparse_with'
from /home/v01d/.gem/ruby/1.9.1/gems/nokogiri-1.4.4/lib/nokogiri/xml/sax/parser.rb:93:in parse_io' from /home/v01d/.gem/ruby/1.9.1/gems/nokogiri-1.4.4/lib/nokogiri/xml/sax/parser.rb:81:inparse'
from /home/v01d/.gem/ruby/1.9.1/gems/rbgccxml-1.0/lib/rbgccxml/sax_parser.rb:15:in parse' from /home/v01d/.gem/ruby/1.9.1/gems/rbgccxml-1.0/lib/rbgccxml/parser.rb:67:inparse'
from /home/v01d/.gem/ruby/1.9.1/gems/rbgccxml-1.0/lib/rbgccxml/rbgccxml.rb:27:in parse' from /home/v01d/.gem/ruby/1.9.1/gems/rbplusplus-1.0.1/lib/rbplusplus/extension.rb:159:insources'
from extconf.rb:9:in block in <main>' from /home/v01d/.gem/ruby/1.9.1/gems/rbplusplus-1.0.1/lib/rbplusplus/extension.rb:82:incall'
from /home/v01d/.gem/ruby/1.9.1/gems/rbplusplus-1.0.1/lib/rbplusplus/extension.rb:82:in initialize' from extconf.rb:7:innew'
from extconf.rb:7:in `

'

Seems to be a nokogiri problem to parse the XML output right? Is there any fix possible?
Thanks

Active?

Is this project still active? Can be still used for making ruby extensions of C++ libs?

Documentation

Need to add wiki documentation to include such things as:

  • using :include_source_dir
  • to_ruby / from_ruby specifications
  • answers other questions asked by the community.

gccxml_cc1plus: error: gccxml_builtins.h: No such file or directory

I'm trying to use c++ code from ruby, http://kheafield.com/code/kenlm/developers/ . I'm getting an error from algorithm:62: which is #including bits/stl_algobase.h. Here is the rbplusplus file and the error follows. I'm not sure if this is a rbplusplus issue, but I don't know how to find out whether it comes from another gem or not.

require 'rubygems'
require 'rbplusplus'
require 'fileutils'
include RbPlusPlus

KENLM_DIR = File.dirname(__FILE__)

Extension.new "kenlm" do |e|
  e.working_dir = File.join(KENLM_DIR, "generated")
  e.sources [
      File.join(KENLM_DIR, "lm/model.hh")
    ],
    :include_paths => KENLM_DIR,
    :include_source_dir => File.join(KENLM_DIR, "lm"),
    :include_source_dir => File.join(KENLM_DIR, "util")

  e.module "Kenlm" do |m|
    node = m.namespace "lm"

    m.module "Ngram" do |ngram|
      node = ngram.namespace "ngram"

      node.classes("TrieModel").use_constructor(
    node.classes("TrieModel").constructors.find(:arguments => [nil])
      )
      node.classes("TrieModel").methods("Score").find(:arguments => [nil, nil, nil]).ignore
    end
  end
end

%ruby kenlm-rbpp.rb
(INFO) Parsing ["./lm/model.hh"]
gccxml_cc1plus: error: gccxml_builtins.h: No such file or directory
In file included from /usr/include/c++/4.6/algorithm:62,
from ./util/sorted_uniform.hh:4,
from ./lm/bhiksha.hh:22,
from ./lm/model.hh:4:
/usr/include/c++/4.6/bits/stl_algobase.h: In function '_OI std::__copy_move_a(_II, _II, _OI)':
/usr/include/c++/4.6/bits/stl_algobase.h:378: error: expected primary-expression before ')' token
/usr/include/c++/4.6/bits/stl_algobase.h:378: error: there are no arguments to '__is_trivial' that depend on a template parameter, so a declaration of '__is_trivial' must be available
/usr/include/c++/4.6/bits/stl_algobase.h:378: error: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
/usr/include/c++/4.6/bits/stl_algobase.h:383: error: '__simple' cannot appear in a constant-expression
/usr/include/c++/4.6/bits/stl_algobase.h:384: error: template argument 2 is invalid
/usr/include/c++/4.6/bits/stl_algobase.h: In function '_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2)':
/usr/include/c++/4.6/bits/stl_algobase.h:573: error: expected primary-expression before ')' token
/usr/include/c++/4.6/bits/stl_algobase.h:573: error: there are no arguments to '__is_trivial' that depend on a template parameter, so a declaration of '__is_trivial' must be available
/usr/include/c++/4.6/bits/stl_algobase.h:578: error: '__simple' cannot appear in a constant-expression
/usr/include/c++/4.6/bits/stl_algobase.h:579: error: template argument 2 is invalid
/usr/include/c++/4.6/bits/stl_algobase.h: In function 'typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), _OutputIterator>::__type std::__fill_n_a(_OutputIterator, _Size, const _Tp&)':
/usr/include/c++/4.6/bits/stl_algobase.h:731: error: expected ;' before '__niter' /usr/include/c++/4.6/bits/stl_algobase.h:732: error: '__niter' was not declared in this scope /usr/include/c++/4.6/bits/stl_algobase.h: In function 'typename __gnu_cxx::__enable_if<std::__is_scalar<_Tp>::__value, _OutputIterator>::__type std::__fill_n_a(_OutputIterator, _Size, const _Tp&)': /usr/include/c++/4.6/bits/stl_algobase.h:743: error: expected;' before '__niter'
/usr/include/c++/4.6/bits/stl_algobase.h:744: error: '__niter' was not declared in this scope
In file included from /usr/include/c++/4.6/bits/stl_tempbuf.h:61,
from /usr/include/c++/4.6/bits/stl_algo.h:64,
from /usr/include/c++/4.6/algorithm:63,
from ./util/sorted_uniform.hh:4,
from ./lm/bhiksha.hh:22,
from ./lm/model.hh:4:
/usr/include/c++/4.6/bits/stl_construct.h: In function 'void std::_Destroy(_ForwardIterator, _ForwardIterator)':
/usr/include/c++/4.6/bits/stl_construct.h:127: error: a function call cannot appear in a constant-expression
/usr/include/c++/4.6/bits/stl_construct.h:127: error: template argument 1 is invalid
/usr/include/c++/4.6/bits/stl_construct.h:128: error: invalid type in declaration before '(' token
/usr/include/c++/4.6/bits/stl_construct.h:128: error: invalid use of qualified-name '::__destroy'
In file included from /usr/include/c++/4.6/bits/stl_algo.h:64,
from /usr/include/c++/4.6/algorithm:63,
from ./util/sorted_uniform.hh:4,
from ./lm/bhiksha.hh:22,
from ./lm/model.hh:4:
/usr/include/c++/4.6/bits/stl_tempbuf.h: In function 'void std::__uninitialized_construct_buf(_ForwardIterator, _ForwardIterator, _Tp&)':
/usr/include/c++/4.6/bits/stl_tempbuf.h:240: error: a function call cannot appear in a constant-expression
/usr/include/c++/4.6/bits/stl_tempbuf.h:240: error: template argument 1 is invalid
/usr/include/c++/4.6/bits/stl_tempbuf.h:241: error: invalid type in declaration before '(' token
/usr/include/c++/4.6/bits/stl_tempbuf.h:241: error: invalid use of qualified-name '::__ucr'
In file included from /usr/include/c++/4.6/algorithm:63,
from ./util/sorted_uniform.hh:4,
from ./lm/bhiksha.hh:22,
from ./lm/model.hh:4:
/usr/include/c++/4.6/bits/stl_algo.h: In function 'void std::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag)':
/usr/include/c++/4.6/bits/stl_algo.h:1603: error: expected primary-expression before ')' token
/usr/include/c++/4.6/bits/stl_algo.h:1603: error: there are no arguments to '__is_pod' that depend on a template parameter, so a declaration of '__is_pod' must be available
/usr/include/c++/4.6/bits/stl_algo.h:1626: error: expected primary-expression before ')' token
/usr/include/c++/4.6/bits/stl_algo.h:1626: error: there are no arguments to '__is_pod' that depend on a template parameter, so a declaration of '__is_pod' must be available
/usr/include/c++/4.6/bits/stl_algo.h: In function '_OIter std::generate_n(_OIter, _Size, _Generator)':
/usr/include/c++/4.6/bits/stl_algo.h:4964: error: expected ;' before '__niter' /usr/include/c++/4.6/bits/stl_algo.h:4965: error: '__niter' was not declared in this scope In file included from /usr/include/c++/4.6/ios:41, from /usr/include/c++/4.6/istream:40, from /usr/include/c++/4.6/sstream:39, from ./util/exception.hh:5, from ./lm/lm_exception.hh:6, from ./lm/config.hh:6, from ./lm/binary_format.hh:4, from ./lm/model.hh:5: /usr/include/c++/4.6/bits/char_traits.h: In static member function 'static const char* std::char_traits<char>::find(const char*, std::size_t, const char&)': /usr/include/c++/4.6/bits/char_traits.h:265: error: '__builtin_memchr' was not declared in this scope In file included from /usr/include/c++/4.6/string:43, from /usr/include/c++/4.6/bits/locale_classes.h:42, from /usr/include/c++/4.6/bits/ios_base.h:43, from /usr/include/c++/4.6/ios:43, from /usr/include/c++/4.6/istream:40, from /usr/include/c++/4.6/sstream:39, from ./util/exception.hh:5, from ./lm/lm_exception.hh:6, from ./lm/config.hh:6, from ./lm/binary_format.hh:4, from ./lm/model.hh:5: /usr/include/c++/4.6/bits/allocator.h: At global scope: /usr/include/c++/4.6/bits/allocator.h:151: error: expected primary-expression before ')' token /usr/include/c++/4.6/bits/allocator.h:151: error: there are no arguments to '__is_empty' that depend on a template parameter, so a declaration of '__is_empty' must be available /usr/include/c++/4.6/bits/allocator.h:168: error: expected primary-expression before ')' token /usr/include/c++/4.6/bits/allocator.h:168: error: there are no arguments to '__is_empty' that depend on a template parameter, so a declaration of '__is_empty' must be available In file included from /usr/include/c++/4.6/vector:64, from ./lm/read_arpa.hh:11, from ./lm/binary_format.hh:6, from ./lm/model.hh:5: /usr/include/c++/4.6/bits/stl_uninitialized.h: In function '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator)': /usr/include/c++/4.6/bits/stl_uninitialized.h:117: error: a function call cannot appear in a constant-expression /usr/include/c++/4.6/bits/stl_uninitialized.h:118: error: a function call cannot appear in a constant-expression /usr/include/c++/4.6/bits/stl_uninitialized.h:118: error: template argument 1 is invalid /usr/include/c++/4.6/bits/stl_uninitialized.h: In function 'void std::uninitialized_fill(_ForwardIterator, _ForwardIterator, const _Tp&)': /usr/include/c++/4.6/bits/stl_uninitialized.h:172: error: a function call cannot appear in a constant-expression /usr/include/c++/4.6/bits/stl_uninitialized.h:172: error: template argument 1 is invalid /usr/include/c++/4.6/bits/stl_uninitialized.h:173: error: invalid type in declaration before '(' token /usr/include/c++/4.6/bits/stl_uninitialized.h:173: error: invalid use of qualified-name '::__uninit_fill' /usr/include/c++/4.6/bits/stl_uninitialized.h: In function 'void std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&)': /usr/include/c++/4.6/bits/stl_uninitialized.h:225: error: a function call cannot appear in a constant-expression /usr/include/c++/4.6/bits/stl_uninitialized.h:225: error: template argument 1 is invalid /usr/include/c++/4.6/bits/stl_uninitialized.h:226: error: invalid type in declaration before '(' token /usr/include/c++/4.6/bits/stl_uninitialized.h:226: error: invalid use of qualified-name '::__uninit_fill_n' In file included from /usr/include/c++/4.6/vector:65, from ./lm/read_arpa.hh:11, from ./lm/binary_format.hh:6, from ./lm/model.hh:5: /usr/include/c++/4.6/bits/stl_vector.h: In member function 'void std::vector<_Tp, _Alloc>::swap(std::vector<_Tp, _Alloc>&)': /usr/include/c++/4.6/bits/stl_vector.h:1028: error: there are no arguments to '__is_empty' that depend on a template parameter, so a declaration of '__is_empty' must be available /usr/include/c++/4.6/bits/stl_vector.h:1028: error: '__is_empty' was not declared in this scope /usr/include/c++/4.6/bits/stl_vector.h:1028: error: template argument 2 is invalid /usr/include/c++/4.6/bits/stl_vector.h:1028: error: invalid type in declaration before '(' token In file included from /usr/include/c++/4.6/vector:66, from ./lm/read_arpa.hh:11, from ./lm/binary_format.hh:6, from ./lm/model.hh:5: /usr/include/c++/4.6/bits/stl_bvector.h: In member function 'void std::vector<bool, _Alloc>::swap(std::vector<bool, _Alloc>&)': /usr/include/c++/4.6/bits/stl_bvector.h:765: error: there are no arguments to '__is_empty' that depend on a template parameter, so a declaration of '__is_empty' must be available /usr/include/c++/4.6/bits/stl_bvector.h:765: error: '__is_empty' was not declared in this scope /usr/include/c++/4.6/bits/stl_bvector.h:765: error: template argument 2 is invalid /usr/include/c++/4.6/bits/stl_bvector.h:766: error: invalid type in declaration before '(' token /usr/lib/ruby/gems/1.8/gems/gccxml_gem-0.9.3-x86_64-linux/./gccxml.rb:29:inparse': Error executing gccxml command line: /usr/lib/ruby/gems/1.8/gems/gccxml_gem-0.9.3-x86_64-linux/bin/gccxml -I. ./lm/model.hh -fxml=/tmp/rbgccxml20120319-30302-vnj9cx-0 (RuntimeError)
from /usr/lib/ruby/gems/1.8/gems/rbgccxml-1.0.3/lib/rbgccxml/parser.rb:56:in parse' from /usr/lib/ruby/gems/1.8/gems/rbgccxml-1.0.3/lib/rbgccxml/rbgccxml.rb:27:inparse'
from /usr/lib/ruby/gems/1.8/gems/rbplusplus-1.0.1/lib/rbplusplus/extension.rb:159:in sources' from kenlm-rbpp.rb:10 from /usr/lib/ruby/gems/1.8/gems/rbplusplus-1.0.1/lib/rbplusplus/extension.rb:82:incall'
from /usr/lib/ruby/gems/1.8/gems/rbplusplus-1.0.1/lib/rbplusplus/extension.rb:82:in initialize' from kenlm-rbpp.rb:8:innew'
from kenlm-rbpp.rb:8

Ruby/C++ Array Conversion

I'm not sure if this is a bug or if I just don't know the right steps to take, but I figured this would be the best place to ask none-the-less. I have a C++ instance method that takes an array of structs as an argument.

struct foo {
  bool bar;
};

class Test {
  public:
    Test();
    ~Test();

    void update(foo*);
};

I know I'm missing the namespace declaration in the above C++ code, but I have it in my real code and things compile fine. When I jump into an irb shell, and do the following:

require 'test'
t = Test.new
f = Foo.new
t.update([f])

I get the following error:

ArgumentError: Unable to convert Array to foo*

Any ideas how I can make it possible to do this?

Thanks for a great and needed project!
Bryan

RuntimeError: Unable to find a castxml executable on your PATH

After executing this simple example...

Extension.new "mu_parser" do |ext|
  ext.sources 'equations-parser/parser/*.h'
end

I'm getting this error message: RuntimeError: Unable to find a castxml executable on your PATH.
Which means the PATH for the castxml is wrong.

How can I set up the PATH for the castxml for the rbplusplus sources call?

For the RbGCCXML gem I can set up the PATH via castxml_path...

RbGCCXML.parse("equations-parser/parser/mpParser.hpp", :castxml_path => 'castXMLSuperbuild-build/castxml/bin/castxml') 

However, I cannot do the same to the rbplusplus gem, am I wrong?

Parsing error when namespaces found in headers

We have header files that already belong to existing namespaces. As soon as the parser encounters anything that is namespaced it crashes with the following output.

(INFO) Parsing ["testing.h"]
/home/tmux/.rvm/gems/ruby-1.9.3-p545@global/gems/bundler-1.5.3/lib/bundler/runtime.rb:220: warning: Insecure world writable dir /opt/tools in PATH, mode 040777
/home/tmux/.rvm/gems/ruby-1.9.3-p545@global/gems/bundler-1.5.3/lib/bundler.rb:295: warning: Insecure world writable dir /opt/tools in PATH, mode 040777
/home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbgccxml-da76add8d536/lib/rbgccxml/sax_parser.rb:46:in `const_get': uninitialized constant RbGCCXML::NamespaceAlias (NameError)
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbgccxml-da76add8d536/lib/rbgccxml/sax_parser.rb:46:in `start_element'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/gems/nokogiri-1.5.9/lib/nokogiri/xml/sax/document.rb:116:in `start_element_namespace'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/gems/nokogiri-1.5.9/lib/nokogiri/xml/sax/parser.rb:95:in `parse_with'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/gems/nokogiri-1.5.9/lib/nokogiri/xml/sax/parser.rb:95:in `parse_io'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/gems/nokogiri-1.5.9/lib/nokogiri/xml/sax/parser.rb:82:in `parse'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbgccxml-da76add8d536/lib/rbgccxml/sax_parser.rb:15:in `parse'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbgccxml-da76add8d536/lib/rbgccxml/parser.rb:67:in `parse'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbgccxml-da76add8d536/lib/rbgccxml/rbgccxml.rb:27:in `parse'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbplusplus-82d025aa0232/lib/rbplusplus/extension.rb:163:in `sources'
    from generate.rb:6:in `block in <main>'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbplusplus-82d025aa0232/lib/rbplusplus/extension.rb:82:in `call'
    from /home/tmux/.rvm/gems/ruby-1.9.3-p545/bundler/gems/rbplusplus-82d025aa0232/lib/rbplusplus/extension.rb:82:in `initialize'
    from generate.rb:5:in `new'
    from generate.rb:5:in `<main>'

It seems rbgccxml is missing some constants that are produced from nokogiri?

Bug in default argument code gen

From the mailing list, trying to wrap https://gitorious.org/realtimeplot ends up generating this:

   {
           typedef void ( realtimeplot::Plot::*line_add_func_type )( float x,float y, int id, realtimeplot::Color color );
           rb_cPlot.define_method("line_add", line_add_func_type(&realtimeplot::Plot::line_add ), (Rice::Arg("x"), Rice::Arg("y"), Rice::Arg("id") = (int)(-0x00000000000000001), Rice::Arg("color") =(realtimeplot::Color::black()())));
   }

The bug is

Rice::Arg("color") = (realtimeplot::Color::black()())

an extra () at the end for some reason.

Rb++ expects callback methods to only take the callback

Rb++ properly wraps and handles this type of method:

void withCallback(func_pointer_type callback)

But the following won't wrap properly:

void withCallbackAndArg(int someArg, char* another, func_pointer_type callback);

Will look into this when needed by myself or someone using rb++.

Re-beautify the resulting C++ code

I took out all formatting thinking I could find a post-processing tool to make it pretty for me, but I haven't found anything of my liking, so I need to re-add code formatting back into rb++'s output.

Trees of virtual classes don't wrap properly

If there's a hierarchy of virtual classes, the type hierarchy in Rice doesn't get setup properly. Need to use the Director classes as supertypes instead of the actual superclasses.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.