Embedded data (RUBY_TYPED_EMBEDDABLE) was only enabled on the anonymous
swig_type_data_type descriptor. Wrapped class objects use the per-class
SwigClass*.cext_type descriptor, whose flags were left zero, so they were never
embedded: the swig_ruby_wrapped_object was allocated separately and, since the
free callback no longer calls ruby_xfree once embedding is compiled in, leaked
on every object.
Set cext_type.flags from a shared SWIG_RUBY_TYPED_DATA_FLAGS macro, used by both
the static swig_type_data_type and the generated per-class descriptors so they
can not drift apart. The flags member, and the macro, only exist from Ruby 2.1
(guarded by RUBY_TYPED_FREE_IMMEDIATELY), so the build still works on Ruby 2.0.
Add test ruby_typeddata_embedded which checks that a wrapped object is embedded
on Ruby 3.3 and later via RTYPEDDATA_EMBEDDED_P.
Assisted-by: Claude Opus 4.8
Ruby-3.3+ allows to embed the wrapper data into the objects memory slot.
This is particular useful for SWIG since the `struct swig_ruby_wrapped_object` is a small and fixed size piece of memory.
Also the rest of the restrictions apply: https://github.com/ruby/ruby/blob/master/doc/extension.rdoc#c-struct-to-ruby-object
This commit reverts several changes of commit 98ea4cdf2d :
1. Revert allocation of `struct swig_ruby_wrapped_object` per malloc:
When using `TypedData_Make_Struct` the corresponding deacclocation should call `ruby_xfree` instead of `free`.
That's the better fix than changing to `malloc` allocation.
2. RTYPEDDATA_DATA is reverted back to RTYPEDDATA_GET_DATA
Because RTYPEDDATA_GET_DATA was in preparation of using RUBY_TYPED_EMBEDDABLE.
3. Revert back to use plain pointer for `$swig_runtime_data_type_pointer`
Because there's no need an no advantage in using `struct swig_ruby_wrapped_object` for this object.
It's makes things only more complicated and needs more memory.
4. The simple type check of $swig_runtime_data_type_pointer was removed
It should be re-added as it protects for accident changes or GC issues.
Rename the per-object wrapper struct from ruby_wrapped_object to
swig_ruby_wrapped_object: a ruby_ prefix in the global namespace is reserved
for the Ruby project itself (swig/swig#3326 review). Also reword the
handleClassName comment.
The other review points are already satisfied by the implementation: the
TypedData descriptors use positional rather than C99 designated initializers
(C90), the generic callbacks take a plainly named parameter, and object
wrapping uses the documented TypedData_Wrap_Struct rather than the internal
Data API.
Assisted-by: Claude Code (Opus 4.8)
The previous commit allocated each object's ruby_wrapped_object with
TypedData_Make_Struct and freed it from the descriptor's free callback. That
only installed the free callback for classes with a destructor or %freefunc, so
the wrapper leaked for destructor-less classes and for the anonymous SWIG::TYPE*
pointer objects, and it freed a Ruby-allocated block with plain free().
Allocate the wrapper with malloc and bind it with TypedData_Wrap_Struct, and
always install the generic mark and free trampolines on every descriptor, the
approach taken in #3456.
The free trampoline runs the per-object free function, if any, and then frees the
wrapper, so malloc and free are paired and nothing leaks regardless of whether the
class owns a destructor. Because TypedData_Wrap_Struct never embeds the data,
RTYPEDDATA_DATA is the correct accessor and the RTYPEDDATA_GET_DATA shim is no longer needed.
See issue #3170.
Assisted-by: Claude Code (deepseek-v4-flash)
The untyped Data API (Data_Wrap_Struct, Data_Get_Struct, DATA_PTR and direct
access to RDATA()->dfree) is deprecated. Ruby 3.4 warns about it by default,
which becomes an error when building generated wrappers with -Werror, and Ruby
4.0 removes the API altogether.
The generated runtime now wraps every object with the TypedData API. Because a
TypedData rb_data_type_t is static per class, it can not carry the per-object
mark and free functions that SWIG needs (ownership is transferred at runtime),
so each object holds a small ruby_wrapped_object that keeps the wrapped pointer
together with its mark and free functions. Generic mark and free callbacks in
the per-class descriptor dispatch to these per-object functions. Each class
gets its own descriptor whose struct name is the C++ class name, which shows up
in Ruby heap dumps and ObjectSpace statistics.
This is not fully backwards compatible: hand written code that reached the
wrapped pointer through DATA_PTR or Data_Get_Struct must instead use the SWIG
conversion functions, which work with old and new SWIG. The ruby_manual_proxy
test is updated to demonstrate the migration.
See issue #3170.
The source of this code is extracted from #3326. Also see followup commit.
Fix deprecation warnings about ANYARGS when compiling C++ code for
SWIG-generated Ruby wrappers with Ruby 3.x.
This is a recurrence of a problem fixed in 4.0.2. Our fix was
conditional on RB_METHOD_DEFINITION_DECL being defined, but Ruby
3.0 stopped defining this.
The macros for casting function pointers are now fully described and also
clarify why the macros act transparently for C even before Ruby 2.7.
In addition, an "if (CPlusPlus)" was removed in the code generator for
global variables in order to keep the distinction between C and C++ in
one place, which is at the definition of said macros.
This commit fixes the signatures of various callback methods
and cleans up the macro definitions used for casting callbacks.
Note that the transparent version of the macro RUBY_METHOD_FUNC
is currently masked behind RUBY_DEVEL, see commit
1d91feaf13
In order to still support strict signature checking and prevent
nasty deprecation warnings, the use of RUBY_METHOD_FUNC had to
be replaced with VALUEFUNC.
This definition ensures the SWIG wrappers keep compiling in older versions
of Ruby given the previous change (which uses RTYPEDDATA_P and hence
requires Ruby 1.9.3). The definition of RTYPEDDATA_P is such that the
previous commit plus the definition should keep the behaviour the same
as before.