rice 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|