rice 2.2.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/COPYING +2 -2
- data/Doxyfile +1 -1
- data/Makefile.in +15 -7
- data/README.md +115 -117
- data/aclocal.m4 +25 -28
- data/ax_cxx_compile_stdcxx.m4 +951 -0
- data/configure +486 -61
- data/configure.ac +3 -3
- data/extconf.rb +6 -2
- data/rice/Array.hpp +16 -16
- data/rice/Array.ipp +11 -11
- data/rice/Class_defn.hpp +1 -0
- data/rice/Constructor.hpp +27 -371
- data/rice/Director.hpp +3 -3
- data/rice/Exception.cpp +2 -7
- data/rice/Hash.hpp +8 -5
- data/rice/Makefile.am +0 -4
- data/rice/Makefile.in +6 -10
- data/rice/Object.cpp +1 -1
- data/rice/Object.ipp +15 -1
- data/rice/Object_defn.hpp +24 -1
- data/rice/String.cpp +2 -7
- data/rice/Struct.cpp +2 -2
- data/rice/Struct.hpp +1 -1
- data/rice/Struct.ipp +1 -1
- data/rice/config.hpp +2 -2
- data/rice/config.hpp.in +2 -2
- data/rice/detail/Arguments.hpp +1 -1
- data/rice/detail/Auto_Function_Wrapper.ipp +512 -1025
- data/rice/detail/Auto_Member_Function_Wrapper.ipp +272 -545
- data/rice/detail/ruby.hpp +0 -4
- data/rice/detail/ruby_version_code.hpp +1 -1
- data/rice/detail/wrap_function.hpp +32 -307
- data/rice/protect.hpp +3 -57
- data/rice/to_from_ruby.ipp +3 -3
- data/ruby/Makefile.in +4 -4
- data/ruby/lib/Makefile.in +4 -4
- data/ruby/lib/version.rb +1 -1
- data/sample/Makefile.am +10 -4
- data/sample/Makefile.in +14 -8
- data/sample/callbacks/extconf.rb +3 -0
- data/sample/callbacks/sample_callbacks.cpp +38 -0
- data/sample/callbacks/test.rb +28 -0
- data/test/Makefile.am +1 -0
- data/test/Makefile.in +15 -9
- data/test/embed_ruby.cpp +21 -0
- data/test/embed_ruby.hpp +4 -0
- data/test/ext/Makefile.in +4 -4
- data/test/test_Address_Registration_Guard.cpp +2 -1
- data/test/test_Array.cpp +2 -1
- data/test/test_Builtin_Object.cpp +2 -1
- data/test/test_Class.cpp +2 -1
- data/test/test_Data_Object.cpp +2 -1
- data/test/test_Data_Type.cpp +2 -1
- data/test/test_Director.cpp +2 -1
- data/test/test_Enum.cpp +2 -1
- data/test/test_Exception.cpp +2 -1
- data/test/test_Hash.cpp +2 -1
- data/test/test_Identifier.cpp +2 -1
- data/test/test_Memory_Management.cpp +2 -1
- data/test/test_Module.cpp +2 -1
- data/test/test_Object.cpp +13 -1
- data/test/test_String.cpp +2 -1
- data/test/test_Struct.cpp +2 -1
- data/test/test_Symbol.cpp +2 -1
- data/test/test_To_From_Ruby.cpp +2 -1
- data/test/test_global_functions.cpp +2 -1
- data/test/test_rice.rb +4 -0
- data/test/unittest.cpp +34 -8
- metadata +26 -11
- data/check_stdcxx_11.ac +0 -103
- data/rice/detail/object_call.hpp +0 -69
- data/rice/detail/object_call.ipp +0 -131
- data/rice/detail/traits.hpp +0 -43
- data/rice/detail/wrap_function.ipp +0 -514
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b94a556a35a6622bc3a5e9ca9f124020b0d22fffa319df33e3aa0bb35bae4d56
|
4
|
+
data.tar.gz: bcd79c325fb7cc04396720a8d987d55ba197079743971f012ca71ceeb16de2df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6122026933d06b8866e486fcd954f6e55a148caab22fe95072cbf5ff6937936d2900e0374b6e276fb14c476c1413833cbd05e536757aea13f7ee431ac163a27
|
7
|
+
data.tar.gz: a7202f164e6cf63259bc3d2b8aa90a7306e53f88305f1c558a4ebd6d1d60b22e7eacf8466667b0fd3ce8123002e44a62a3896f9e4ecb69b3b412f09b23bf64af
|
data/COPYING
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
Copyright (C)
|
2
|
-
|
1
|
+
Copyright (C) 2020 Jason Roelofs <jasongroelofs@gmail.com>
|
2
|
+
Paul Brannan <curlypaul924@gmail.com>,
|
3
3
|
|
4
4
|
Redistribution and use in source and binary forms, with or without
|
5
5
|
modification, are permitted provided that the following conditions
|
data/Doxyfile
CHANGED
@@ -38,7 +38,7 @@ PROJECT_NAME = "Rice"
|
|
38
38
|
# could be handy for archiving the generated documentation or if some version
|
39
39
|
# control system is used.
|
40
40
|
|
41
|
-
PROJECT_NUMBER =
|
41
|
+
PROJECT_NUMBER = 3.0.0
|
42
42
|
|
43
43
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
44
44
|
# for a project that appears at the top of each page and should give viewer a
|
data/Makefile.in
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
# Makefile.in generated by automake 1.16.
|
1
|
+
# Makefile.in generated by automake 1.16.3 from Makefile.am.
|
2
2
|
# @configure_input@
|
3
3
|
|
4
|
-
# Copyright (C) 1994-
|
4
|
+
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
5
5
|
|
6
6
|
# This Makefile.in is free software; the Free Software Foundation
|
7
7
|
# gives unlimited permission to copy and/or distribute it,
|
@@ -119,7 +119,7 @@ build_triplet = @build@
|
|
119
119
|
host_triplet = @host@
|
120
120
|
subdir = .
|
121
121
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
122
|
-
am__aclocal_m4_deps = $(top_srcdir)/
|
122
|
+
am__aclocal_m4_deps = $(top_srcdir)/ax_cxx_compile_stdcxx.m4 \
|
123
123
|
$(top_srcdir)/ruby.ac $(top_srcdir)/doxygen.ac \
|
124
124
|
$(top_srcdir)/configure.ac
|
125
125
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
@@ -190,7 +190,7 @@ CSCOPE = cscope
|
|
190
190
|
DIST_SUBDIRS = $(SUBDIRS)
|
191
191
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/doxygen.am \
|
192
192
|
$(top_srcdir)/rice/detail/ruby_version_code.hpp.in COPYING \
|
193
|
-
|
193
|
+
config.guess config.sub depcomp install-sh missing
|
194
194
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
195
195
|
distdir = $(PACKAGE)-$(VERSION)
|
196
196
|
top_distdir = "$(distdir)"
|
@@ -229,6 +229,8 @@ am__relativize = \
|
|
229
229
|
DIST_ARCHIVES = "$(distdir)".tar.gz
|
230
230
|
GZIP_ENV = --best
|
231
231
|
DIST_TARGETS = dist-gzip
|
232
|
+
# Exists only to be overridden by the user if desired.
|
233
|
+
AM_DISTCHECK_DVI_TARGET = dvi
|
232
234
|
distuninstallcheck_listfiles = find . -type f -print
|
233
235
|
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
|
234
236
|
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
|
@@ -275,7 +277,7 @@ ECHO_C = @ECHO_C@
|
|
275
277
|
ECHO_N = @ECHO_N@
|
276
278
|
ECHO_T = @ECHO_T@
|
277
279
|
EXEEXT = @EXEEXT@
|
278
|
-
|
280
|
+
HAVE_CXX14 = @HAVE_CXX14@
|
279
281
|
INSTALL = @INSTALL@
|
280
282
|
INSTALL_DATA = @INSTALL_DATA@
|
281
283
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
@@ -634,6 +636,10 @@ dist-xz: distdir
|
|
634
636
|
tardir="$(distdir)" && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >"$(distdir)".tar.xz
|
635
637
|
$(am__post_remove_distdir)
|
636
638
|
|
639
|
+
dist-zstd: distdir
|
640
|
+
tardir="$(distdir)" && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >"$(distdir)".tar.zst
|
641
|
+
$(am__post_remove_distdir)
|
642
|
+
|
637
643
|
dist-tarZ: distdir
|
638
644
|
@echo WARNING: "Support for distribution archives compressed with" \
|
639
645
|
"legacy program 'compress' is deprecated." >&2
|
@@ -676,6 +682,8 @@ distcheck: dist
|
|
676
682
|
eval GZIP= gzip $(GZIP_ENV) -dc "$(distdir)".shar.gz | unshar ;;\
|
677
683
|
*.zip*) \
|
678
684
|
unzip "$(distdir)".zip ;;\
|
685
|
+
*.tar.zst*) \
|
686
|
+
zstd -dc "$(distdir)".tar.zst | $(am__untar) ;;\
|
679
687
|
esac
|
680
688
|
chmod -R a-w "$(distdir)"
|
681
689
|
chmod u+w "$(distdir)"
|
@@ -691,7 +699,7 @@ distcheck: dist
|
|
691
699
|
$(DISTCHECK_CONFIGURE_FLAGS) \
|
692
700
|
--srcdir=../.. --prefix="$$dc_install_base" \
|
693
701
|
&& $(MAKE) $(AM_MAKEFLAGS) \
|
694
|
-
&& $(MAKE) $(AM_MAKEFLAGS)
|
702
|
+
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
|
695
703
|
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
696
704
|
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
697
705
|
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
@@ -852,7 +860,7 @@ uninstall-am:
|
|
852
860
|
am--refresh check check-am clean clean-cscope clean-generic \
|
853
861
|
cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
|
854
862
|
dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
|
855
|
-
distcheck distclean distclean-generic distclean-tags \
|
863
|
+
dist-zstd distcheck distclean distclean-generic distclean-tags \
|
856
864
|
distcleancheck distdir distuninstallcheck dvi dvi-am html \
|
857
865
|
html-am info info-am install install-am install-data \
|
858
866
|
install-data-am install-dvi install-dvi-am install-exec \
|
data/README.md
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
# Introduction {#intro}
|
4
4
|
|
5
|
-
Rice is a C++ interface to Ruby's C API.
|
5
|
+
Rice is a C++ interface to Ruby's C API. It provides a type-safe and
|
6
6
|
exception-safe interface in order to make embedding Ruby and writing
|
7
|
-
Ruby extensions with C++ easier.
|
8
|
-
ways, but also attempts to provide an object-oriented interface to all
|
7
|
+
Ruby extensions with C++ easier. It is similar to Boost.Python or pybind11
|
8
|
+
in many ways, but also attempts to provide an object-oriented interface to all
|
9
9
|
of the Ruby C API.
|
10
10
|
|
11
11
|
What Rice gives you:
|
@@ -16,7 +16,7 @@ What Rice gives you:
|
|
16
16
|
|
17
17
|
# Project Details {#project}
|
18
18
|
|
19
|
-
The source is hosted on
|
19
|
+
The source is hosted on GitHub: http://github.com/jasonroelofs/rice
|
20
20
|
|
21
21
|
Bug tracking: http://github.com/jasonroelofs/rice/issues
|
22
22
|
|
@@ -36,8 +36,9 @@ Building it locally from a clone of the repository is as follows:
|
|
36
36
|
make
|
37
37
|
~~~
|
38
38
|
|
39
|
-
Rice is known to work on *nix and
|
40
|
-
|
39
|
+
Rice is known to work on *nix, OSX, and Windows.
|
40
|
+
|
41
|
+
Rice requires a C++ compiler with support for C++14 or later.
|
41
42
|
|
42
43
|
# Tutorial {#tutorial}
|
43
44
|
|
@@ -53,7 +54,7 @@ The first step is to create an extconf.rb file:
|
|
53
54
|
create_makefile('test')
|
54
55
|
~~~
|
55
56
|
|
56
|
-
Note that we use `mkmf-rice` instead of `mkmf`.
|
57
|
+
Note that we use `mkmf-rice` instead of `mkmf`. This will ensure that the
|
57
58
|
extension will be linked with standard C++ library along with the Rice
|
58
59
|
library, and allow access to the Rice header files.
|
59
60
|
|
@@ -66,19 +67,19 @@ Next we create our extension and save it to test.cpp:
|
|
66
67
|
}
|
67
68
|
~~~
|
68
69
|
|
69
|
-
Note the extern "C" line above.
|
70
|
-
function `Init_test` should have C linkage and calling convention.
|
70
|
+
Note the extern "C" line above. This tells the compiler that the
|
71
|
+
function `Init_test` should have C linkage and calling convention. This
|
71
72
|
turns off name mangling so that the Ruby interpreter will be able to
|
72
73
|
find the function (remember that Ruby is written in C, not C++).
|
73
74
|
|
74
75
|
So far we haven't put anything into the extension, so it isn't
|
75
|
-
particularly useful.
|
76
|
+
particularly useful. The next step is to define a class so we can add
|
76
77
|
methods to it.
|
77
78
|
|
78
79
|
|
79
80
|
## Defining clases {#classes}
|
80
81
|
|
81
|
-
Defining a class in Rice is
|
82
|
+
Defining a class in Rice is a single call:
|
82
83
|
|
83
84
|
~~~{.cpp}
|
84
85
|
#include "rice/Class.hpp"
|
@@ -93,7 +94,7 @@ Defining a class in Rice is easy:
|
|
93
94
|
~~~
|
94
95
|
|
95
96
|
This will create a class called `Test` that inherits from `Object`. If we
|
96
|
-
wanted to inherit from a different class, we
|
97
|
+
wanted to inherit from a different class, we do so with the second parameter:
|
97
98
|
|
98
99
|
~~~{.cpp}
|
99
100
|
#include "rice/Class.hpp"
|
@@ -153,8 +154,8 @@ Now let's add a method to our class:
|
|
153
154
|
}
|
154
155
|
~~~
|
155
156
|
|
156
|
-
Here we add a method `%Test#hello` that
|
157
|
-
"Hello, World".
|
157
|
+
Here we add a method `%Test#hello` that returns the string
|
158
|
+
"Hello, World". The method takes self as an implicit parameter, but
|
158
159
|
isn't used, so we comment it out to prevent a compiler warning.
|
159
160
|
|
160
161
|
We could also add an `#initialize` method to our class:
|
@@ -190,8 +191,8 @@ The `initialize` method sets an instance variable `@foo` to the value 42.
|
|
190
191
|
The number is automatically converted to a `Fixnum` before doing the
|
191
192
|
assignment.
|
192
193
|
|
193
|
-
Note that we're chaining calls on the `Class` object.
|
194
|
-
functions in `Module` and `Class` return a reference to self
|
194
|
+
Note that we're chaining calls on the `Class` object. Most member
|
195
|
+
functions in `Module` and `Class` return a reference to `self`, so we can
|
195
196
|
chain as many calls as we want to define as many methods as we want.
|
196
197
|
|
197
198
|
|
@@ -276,8 +277,8 @@ Ruby types:
|
|
276
277
|
Object to_ruby(T const & x);
|
277
278
|
~~~
|
278
279
|
|
279
|
-
Rice
|
280
|
-
types. To define your own conversion,
|
280
|
+
Rice includes default specializations for many of the builtin
|
281
|
+
types. To define your own conversion, write a template specialization:
|
281
282
|
|
282
283
|
~~~{.cpp}
|
283
284
|
template<>
|
@@ -325,8 +326,8 @@ calls:
|
|
325
326
|
works as expected.
|
326
327
|
|
327
328
|
The `Data_Object` class is a wrapper for the `Data_Wrap_Struct` and the
|
328
|
-
`Data_Get_Struct` macros in C extensions.
|
329
|
-
unwrap any class that has been assigned to a `Data_Type`.
|
329
|
+
`Data_Get_Struct` macros in C extensions. It can be used to wrap or
|
330
|
+
unwrap any class that has been assigned to a `Data_Type`. It inherits
|
330
331
|
from `Object`, so any member functions we can call on an `Object` we can
|
331
332
|
also call on a `Data_Object`:
|
332
333
|
|
@@ -401,11 +402,11 @@ and call it from inside Ruby:
|
|
401
402
|
test.error()
|
402
403
|
~~~
|
403
404
|
|
404
|
-
we would get an exception.
|
405
|
-
C++ exception it catches into a Ruby exception.
|
405
|
+
we would get an exception. Rice will automatically convert any
|
406
|
+
C++ exception it catches into a Ruby exception. But what if we wanted
|
406
407
|
to use a custom error message when we convert the exception, or what if
|
407
|
-
we wanted to convert to a different type of exception?
|
408
|
-
|
408
|
+
we wanted to convert to a different type of exception? We can write
|
409
|
+
an exception handler like so:
|
409
410
|
|
410
411
|
~~~{.cpp}
|
411
412
|
extern "C"
|
@@ -430,7 +431,7 @@ The `handle_my_exception` function need only rethrow the exception as a
|
|
430
431
|
}
|
431
432
|
~~~
|
432
433
|
|
433
|
-
And what if we want to call Ruby code from C++?
|
434
|
+
And what if we want to call Ruby code from C++? These exceptions are
|
434
435
|
also converted:
|
435
436
|
|
436
437
|
~~~{.cpp}
|
@@ -441,7 +442,7 @@ also converted:
|
|
441
442
|
~~~
|
442
443
|
|
443
444
|
Internally whenever Rice catches a C++ or a Ruby exception, it converts
|
444
|
-
it to an `Exception` object.
|
445
|
+
it to an `Exception` object. This object will later be re-raised as a
|
445
446
|
Ruby exception when control is returned to the Ruby VM.
|
446
447
|
|
447
448
|
Rice uses a similar class called `Jump_Tag` to handle symbols thrown by
|
@@ -504,7 +505,7 @@ wrapper functions for base classes typically don't know how to accept
|
|
504
505
|
pointers to derived classes. It is possible to write this logic, but
|
505
506
|
the code is nontrivial.
|
506
507
|
|
507
|
-
|
508
|
+
Rice also provides a solution to this problem:
|
508
509
|
|
509
510
|
~~~{.cpp}
|
510
511
|
class Base
|
@@ -538,7 +539,7 @@ Rice does not support multiple inheritance.
|
|
538
539
|
## Overloaded functions {#overloading}
|
539
540
|
|
540
541
|
If you try to create a member function pointer to an overloaded
|
541
|
-
function, you will get an error.
|
542
|
+
function, you will get an error. So how do we wrap classes that have
|
542
543
|
overloaded functions?
|
543
544
|
|
544
545
|
Consider a class that uses this idiom for accessors:
|
@@ -584,8 +585,8 @@ array of char?
|
|
584
585
|
|
585
586
|
Because the second case is the most common use case (a pointer to the
|
586
587
|
first character of a C string), Rice provides a default conversion that
|
587
|
-
treats a `char *` as a C string.
|
588
|
-
pointer to a char instead?
|
588
|
+
treats a `char *` as a C string. But suppose the above function actually
|
589
|
+
expects to receive a pointer to a single char instead?
|
589
590
|
|
590
591
|
If we write this:
|
591
592
|
|
@@ -599,7 +600,8 @@ If we write this:
|
|
599
600
|
|
600
601
|
It will likely have the wrong behavior.
|
601
602
|
|
602
|
-
To avoid this problem, it is necessary to write a wrapper function
|
603
|
+
To avoid this problem, it is necessary to write a wrapper function where
|
604
|
+
the extension can be more explicit about how to handle the parameters:
|
603
605
|
|
604
606
|
~~~{.cpp}
|
605
607
|
Object wrap_foo(Object o)
|
@@ -656,8 +658,8 @@ it is necessary to define this in Rice explicitly using `Rice::Arg`:
|
|
656
658
|
}
|
657
659
|
~~~
|
658
660
|
|
659
|
-
The syntax here is
|
660
|
-
parameter is not important here (
|
661
|
+
The syntax here is `Arg(nameOfParameter)[ = defaultValue]`. The name of the
|
662
|
+
parameter is not important here (it is for readability), but the value set via `operator=`
|
661
663
|
must match the type of the parameter. As such it may be necessary to
|
662
664
|
explicitly cast the default value.
|
663
665
|
|
@@ -689,12 +691,12 @@ This also works with Constructors:
|
|
689
691
|
|
690
692
|
## Director {#director}
|
691
693
|
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
`
|
694
|
+
Polymorphism creates yet another wrinkle in building exceptions around C++ code,
|
695
|
+
because now we have to deal with cross-language polymorphism, where C++ can call
|
696
|
+
into a Ruby subclass, and a Ruby subclass can `super` back into C++ land. `super`
|
697
|
+
calls already work through define_class, but making code travel from C++ into Ruby
|
698
|
+
via polymorphism is tricker. Rice provides the `Rice::Director` class and the
|
699
|
+
`define_director` method to enable this code path.
|
698
700
|
|
699
701
|
Like `SWIG_Director`, `Rice::Director` is a class that is used to build a proxy class
|
700
702
|
to properly send execution up or down the object hierarchy for that class. Take
|
@@ -709,13 +711,13 @@ the following class:
|
|
709
711
|
};
|
710
712
|
~~~
|
711
713
|
|
712
|
-
Due to the abstract nature of this class,
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
any Ruby subclasses.
|
714
|
+
Due to the abstract nature of this class, we cannot directly wrap it in Rice, as
|
715
|
+
any C++ compiler will complain about trying to instantiate a virtual class.
|
716
|
+
Even without the pure virtual function, any call to `VirtualBase::doWork` will stop
|
717
|
+
at the C++ level and execution will not pass down into any Ruby subclasses.
|
717
718
|
|
718
|
-
To properly wrap both of these methods, use a `Rice::Director` subclass as a proxy
|
719
|
+
To properly wrap both of these methods, use a `Rice::Director` subclass as a proxy
|
720
|
+
and use this new proxy class as the type to wrap with `define_class`:
|
719
721
|
|
720
722
|
~~~{.cpp}
|
721
723
|
#include "rice/Director.hpp"
|
@@ -756,7 +758,7 @@ First, the class needs to subclass both the virtual class in question and `Rice:
|
|
756
758
|
~~~
|
757
759
|
|
758
760
|
For `Rice::Director` to work its magic, every instance of this class needs to
|
759
|
-
have a handle to
|
761
|
+
have a handle to its Ruby instance. The constructor
|
760
762
|
must take a `Rice::Object` as the first argument and pass it up into
|
761
763
|
`Rice::Director`. The code here is the minimum required for a `Rice::Director` proxy.
|
762
764
|
|
@@ -770,17 +772,13 @@ must take a `Rice::Object` as the first argument and pass it up into
|
|
770
772
|
}
|
771
773
|
~~~
|
772
774
|
|
773
|
-
Here the
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
`
|
778
|
-
|
779
|
-
|
780
|
-
The `default_doWork` method will be used as Rice's hookup of calling back up the
|
781
|
-
hierarchy (wrapping is below). This method needs to do one of two things: call
|
782
|
-
up the class hierarchy, as seen here, or call `raisePureVirtual()` as seen in the
|
783
|
-
processWorker example:
|
775
|
+
Here the proxy class implements the virtual methods and provides implementations
|
776
|
+
that delegate execution in the correct direction. The actual method calls into Ruby,
|
777
|
+
providing all necessary type conversions to and from C++ types. The other method
|
778
|
+
is how Ruby calls back into C++ and is the method that must be exposed with
|
779
|
+
`define_method`. The `default_` prefix is a naming convention to help keep straight
|
780
|
+
which methods perform which function. If Ruby should never call into C++, then the
|
781
|
+
`default_` implementation should call `raisePureVirtual()`:
|
784
782
|
|
785
783
|
~~~{.cpp}
|
786
784
|
int default_processWorker() {
|
@@ -807,7 +805,7 @@ void Init_virtual() {
|
|
807
805
|
|
808
806
|
The wrapping is the same as is described earlier in this document. Expose the class
|
809
807
|
`VirtualBase`, and register `VirtualBaseProxy` as a director proxy of `VirtualBase` with
|
810
|
-
`Rice::Data_Type::define_director`, then `
|
808
|
+
`Rice::Data_Type::define_director`, then `define_method`s pointing to the proxy methods as necessary.
|
811
809
|
|
812
810
|
You must use the `Rice::Director` proxy class in the Constructor line, this allows proper
|
813
811
|
object construction / destruction of the types in question.
|
@@ -854,63 +852,63 @@ test/test_Data_Type.cpp.
|
|
854
852
|
There are a number of common problems when writing C or C++ extensions
|
855
853
|
for Ruby:
|
856
854
|
|
857
|
-
- Type safety.
|
858
|
-
VALUE.
|
855
|
+
- Type safety. It is easy to mix-up integral types such as ID and
|
856
|
+
VALUE. Some of the functions in the Ruby API are not consistent with
|
859
857
|
which types they take (e.g. rb_const_defined takes an ID and
|
860
858
|
rb_mod_remove_const takes a Symbol).
|
861
859
|
|
862
|
-
- DRY principle.
|
863
|
-
function takes is easy to get wrong.
|
860
|
+
- DRY principle. Specifying the number of arguments that each wrapped
|
861
|
+
function takes is easy to get wrong. Adding a new argument to the
|
864
862
|
function means that the number of arguments passed to rb_define_method
|
865
863
|
must also be updated.
|
866
864
|
|
867
|
-
- Type conversion.
|
868
|
-
to and from ruby types.
|
869
|
-
different forms.
|
865
|
+
- Type conversion. There are many different functions to convert data
|
866
|
+
to and from ruby types. Many of them have different semantics or
|
867
|
+
different forms. For example, to convert a string, one might use the
|
870
868
|
StringValue macro, but to convert a fixnum, one might use FIX2INT.
|
871
869
|
Unwrapping previously wrapped C data uses yet another form.
|
872
870
|
|
873
|
-
- Exception safety.
|
871
|
+
- Exception safety. It is imperative that C++ exceptions never make
|
874
872
|
their way into C code, and it is also imperative that a Ruby exception
|
875
873
|
never escape while there are objects on the stack with nontrivial
|
876
|
-
destructors.
|
874
|
+
destructors. Rules for when it is okay to use which exceptions are
|
877
875
|
difficult to get right, especially as code is maintained through time.
|
878
876
|
|
879
|
-
- Thread safety.
|
877
|
+
- Thread safety. Because the Ruby interpreter is not thread-safe,
|
880
878
|
the Ruby interpreter must not be run from more than one thread.
|
881
879
|
Because of tricks the GC and scheduler play with the C stack, it's not
|
882
880
|
enough to ensure that only one thread runs the interpreter at any
|
883
881
|
given time; once the interpreter has been run from one thread, it must
|
884
|
-
only ever be run from that thread in the future.
|
882
|
+
only ever be run from that thread in the future. Additionally,
|
885
883
|
because Ruby copies the stack when it switches threads, C++ code must
|
886
884
|
be careful not to access objects in one Ruby thread that were created
|
887
885
|
on the stack in another Ruby thread.
|
888
886
|
|
889
|
-
- C-based API.
|
887
|
+
- C-based API. The Ruby API is not always convenient for accessing
|
890
888
|
Ruby data structurs such as Hash and Array, especially when writing C++
|
891
889
|
code, as the interface for these containers is not consistent with
|
892
890
|
standard containers.
|
893
891
|
|
894
|
-
- Calling convention.
|
895
|
-
follow the C calling convention.
|
892
|
+
- Calling convention. Function pointers passed into the Ruby API must
|
893
|
+
follow the C calling convention. This means that it is not possible to
|
896
894
|
pass a pointer to a template function or static member function (that
|
897
895
|
is, it will work on some platforms, but isn't portable).
|
898
896
|
|
899
|
-
- Inheritance.
|
897
|
+
- Inheritance. When wrapping C++ objects, it is easy to store a
|
900
898
|
pointer to a derived class, but then methods in the base class must have
|
901
|
-
knowledge of the derived class in order to unwrap the object.
|
899
|
+
knowledge of the derived class in order to unwrap the object. It is
|
902
900
|
possible to always store a pointer to the base class and then
|
903
901
|
dynamic_cast the pointer to the derived type when necessary, but this
|
904
902
|
can be slow and cumbersome, and it isn't likely to work with multiple
|
905
|
-
inheritance.
|
903
|
+
inheritance. A system that properly handles inheritance for all corner
|
906
904
|
cases is nontrivial.
|
907
905
|
|
908
|
-
- Multiple inheritance.
|
909
|
-
the Ruby object model uses single inheritance with mixins.
|
906
|
+
- Multiple inheritance. C++ supports true multiple inheritance, but
|
907
|
+
the Ruby object model uses single inheritance with mixins. When
|
910
908
|
wrapping a library whose public interface uses multiple inheritance,
|
911
909
|
care must be taken in constructing the mapping.
|
912
910
|
|
913
|
-
- GC safety.
|
911
|
+
- GC safety. All live Ruby objects must be marked during the garbage
|
914
912
|
collector's mark phase, otherwise they will be prematurely destroyed.
|
915
913
|
The general rule is that object references stored on the heap should be
|
916
914
|
either registered with rb_gc_register_address or marked by a data
|
@@ -918,92 +916,92 @@ object's mark function; object references stored on the stack will be
|
|
918
916
|
automatically marked, provided the Ruby interpreter was properly
|
919
917
|
initialized at startup.
|
920
918
|
|
921
|
-
- Callbacks.
|
922
|
-
typically implements callbacks via procs.
|
919
|
+
- Callbacks. C implements callbacks via function pointers, while Ruby
|
920
|
+
typically implements callbacks via procs. Writing an adapter function
|
923
921
|
to call the proc is not difficult, but there is much opportunity for
|
924
922
|
error (particularly with exception-safety).
|
925
923
|
|
926
|
-
- Data serialization.
|
927
|
-
are not marshalable.
|
924
|
+
- Data serialization. By default data objects defined at the C layer
|
925
|
+
are not marshalable. The user must explicitly define functions to
|
928
926
|
marshal the data member-by-member.
|
929
927
|
|
930
928
|
Rice addresses these issues in many ways:
|
931
929
|
|
932
|
-
- Type safety.
|
933
|
-
such as Object, Identifier, Class, Module, and String.
|
930
|
+
- Type safety. Rice provides encapsulation for all builtin types,
|
931
|
+
such as Object, Identifier, Class, Module, and String. It
|
934
932
|
automatically checks the dynamic type of an object before constructing
|
935
933
|
an instance of a wrapper.
|
936
934
|
|
937
|
-
- DRY principle.
|
935
|
+
- DRY principle. Rice uses introspection through the use of templates
|
938
936
|
and function overloading to automatically determine the number and types
|
939
|
-
of arguments to functions.
|
937
|
+
of arguments to functions. Default arguments must still be handled
|
940
938
|
explicitly, however.
|
941
939
|
|
942
|
-
- Type conversions.
|
940
|
+
- Type conversions. Rice provides cast-style to_ruby<> and
|
943
941
|
from_ruby<> template functions to simplify explicit type conversions.
|
944
942
|
Automatic type conversions for parameters and return values are
|
945
943
|
generated for all wrapped functions.
|
946
944
|
|
947
|
-
- Exception safety.
|
948
|
-
provides a mechanism for converting user-defined exception types.
|
945
|
+
- Exception safety. Rice automatically converts common exceptions and
|
946
|
+
provides a mechanism for converting user-defined exception types. Rice
|
949
947
|
also provides convenience functions for converting exceptions when
|
950
948
|
calling back into ruby code.
|
951
949
|
|
952
|
-
- Thread safety.
|
953
|
-
safety.
|
950
|
+
- Thread safety. Rice provides no mechanisms for dealing with thread
|
951
|
+
safety. Many common thread safety issues should be alleviated by YARV,
|
954
952
|
which supports POSIX threads.
|
955
953
|
|
956
|
-
- C++-based API.
|
954
|
+
- C++-based API. Rice provides an object-oriented C++-style API to
|
957
955
|
most common functions in the Ruby C API.
|
958
956
|
|
959
|
-
- Calling convention.
|
957
|
+
- Calling convention. Rice automatically uses C calling convention
|
960
958
|
for all function pointers passed into the Ruby API.
|
961
959
|
|
962
|
-
- Inheritance.
|
960
|
+
- Inheritance. Rice provides automatic conversion to the base class
|
963
961
|
type when a wrapped member function is called on the base class.
|
964
962
|
|
965
|
-
- Multiple inheritance.
|
966
|
-
inheritance.
|
963
|
+
- Multiple inheritance. Rice provides no mechanism for multiple
|
964
|
+
inheritance. Multiple inheritance can be simulated via mixins, though
|
967
965
|
this is not yet as easy as it could be.
|
968
966
|
|
969
|
-
- GC safety.
|
970
|
-
interacting with the garbage collector.
|
967
|
+
- GC safety. Rice provides a handful of convenience classes for
|
968
|
+
interacting with the garbage collector. There are still basic rules
|
971
969
|
which must be followed to ensure that objects get properly destroyed.
|
972
970
|
|
973
|
-
- Callbacks.
|
971
|
+
- Callbacks. Rice provides a handful of convenience classes for
|
974
972
|
dealing with callbacks.
|
975
973
|
|
976
|
-
- Data serialization.
|
974
|
+
- Data serialization. Rice provides no mechanism for data
|
977
975
|
serialization, but it is likely this may be added in a future release.
|
978
976
|
|
979
977
|
|
980
978
|
# What Rice is Not {#what_not}
|
981
979
|
|
982
|
-
There are a number projects which server similar functions to Rice.
|
983
|
-
such popular projects are SWIG and Boost.Python.
|
980
|
+
There are a number projects which server similar functions to Rice. Two
|
981
|
+
such popular projects are SWIG and Boost.Python. Rice has some
|
984
982
|
distinct features which set it apart from both of these projects.
|
985
983
|
|
986
|
-
Rice is not trying to replace SWIG.
|
987
|
-
interface generator.
|
988
|
-
Ruby C API.
|
984
|
+
Rice is not trying to replace SWIG. Rice is not a generic wrapper
|
985
|
+
interface generator. Rice is a C++ library for interfacing with the
|
986
|
+
Ruby C API. This provides a very natural way for C++ programmers to
|
989
987
|
wrap their C++ code, without having to learn a new domain-specific
|
990
|
-
language.
|
991
|
-
together; a SWIG module could be written to generate Rice code.
|
988
|
+
language. However, there is no reason why SWIG and Rice could not work
|
989
|
+
together; a SWIG module could be written to generate Rice code. Such a
|
992
990
|
module would combine the portability of SWIG with the maintainability of
|
993
991
|
Rice (I have written extensions using both, and I have found Rice
|
994
992
|
extensions to be more maintainable when the interface is constantly
|
995
|
-
changing.
|
993
|
+
changing. Your mileage may vary).
|
996
994
|
|
997
995
|
Rice is also not trying to simply be a Ruby version of Boost.Python.
|
998
996
|
Rice does use some of the same template tricks that Boost.Python uses,
|
999
|
-
however there are some important distinctions.
|
997
|
+
however there are some important distinctions. First of all,
|
1000
998
|
Boost.Python attempts to create a declarative DSL in C++ using
|
1001
|
-
templates.
|
999
|
+
templates. Rice is a wrapper around the Ruby C API and attempts to make
|
1002
1000
|
its interface look like an OO version of the API; this means that class
|
1003
|
-
declarations look procedural rather than declarative.
|
1004
|
-
Ruby object model is different from the python object model.
|
1001
|
+
declarations look procedural rather than declarative. Secondly, the
|
1002
|
+
Ruby object model is different from the python object model. This is
|
1005
1003
|
reflected in the interface to Rice; it mimics the Ruby object model at
|
1006
|
-
the C++ level.
|
1004
|
+
the C++ level. Thirdly, Rice uses Ruby as a code generator; I find this
|
1007
1005
|
to be much more readable than using the Boost preprocessor library.
|
1008
1006
|
|
1009
1007
|
|
@@ -1016,7 +1014,7 @@ today, and did not suit the needs of the project.
|
|
1016
1014
|
|
1017
1015
|
Excruby was written not as a wrapper for the Ruby API, but rather as a
|
1018
1016
|
set of helper functions and classes for interfacing with the Ruby
|
1019
|
-
interpreter in an exception-safe manner.
|
1017
|
+
interpreter in an exception-safe manner. Over the course of five years,
|
1020
1018
|
the project grew into wrappers for pieces of the API, but the original
|
1021
1019
|
helper functions remained as part of the public interface.
|
1022
1020
|
|
@@ -1025,7 +1023,7 @@ multiple ways of accomplishing most tasks -- directly through the C API,
|
|
1025
1023
|
through a low-level wrapper around the C API, and through a high-level
|
1026
1024
|
abstraction of the lower-level interfaces.
|
1027
1025
|
|
1028
|
-
Rice was then born in an attempt to clean up the interface.
|
1026
|
+
Rice was then born in an attempt to clean up the interface. Rice keeps
|
1029
1027
|
the lower-level wrappers, but as an implementation detail; the public
|
1030
1028
|
interface is truly a high-level abstraction around the Ruby C API.
|
1031
1029
|
|
@@ -1044,9 +1042,9 @@ collector.
|
|
1044
1042
|
|
1045
1043
|
- If a reference counted object is being wrapped, or if another type
|
1046
1044
|
of smart pointer is wrapped, ensure that only one mechanism is used to
|
1047
|
-
destroy the object.
|
1045
|
+
destroy the object. In general, the smart pointer manages the
|
1048
1046
|
allocation of the object, and Ruby should hold only a reference to the
|
1049
|
-
smart pointer.
|
1047
|
+
smart pointer. When the garbage collector determines that it is time to
|
1050
1048
|
clean up the object, the smart pointer will be destroyed, decrementing
|
1051
1049
|
the reference count; when the reference count drops to 0, underlying
|
1052
1050
|
object will be destroyed.
|