Skip to content

feat: Ruby 3.4 support — migrate from Data_Wrap_Struct to TypedData#30

Merged
ohai merged 4 commits into
ohai:masterfrom
smalruby:smalruby/ruby-3.4-support
Apr 7, 2026
Merged

feat: Ruby 3.4 support — migrate from Data_Wrap_Struct to TypedData#30
ohai merged 4 commits into
ohai:masterfrom
smalruby:smalruby/ruby-3.4-support

Conversation

@takaokouji
Copy link
Copy Markdown
Contributor

Summary

Migrate all Data_Wrap_Struct / Data_Get_Struct to TypedData_Wrap_Struct / TypedData_Get_Struct for Ruby 3.4 compatibility.

Ruby 3.4 deprecates the old Data_Wrap_Struct / Data_Get_Struct API in favor of TypedData. This PR eliminates all deprecation warnings (previously 90+) while maintaining backward compatibility with Ruby 3.3.x.

Approach

A new DEFINE_DATA_TYPE helper macro in rubysdl2_internal.h makes migration straightforward:

#define DEFINE_DATA_TYPE(struct_name, free_func) \
    static const rb_data_type_t struct_name##_data_type = { \
        #struct_name, \
        { NULL, (void (*)(void*))(free_func), NULL }, \
        NULL, NULL, 0 \
    };

The existing DEFINE_GETTER macro is updated to use TypedData_Get_Struct, and all Data_Wrap_Struct calls are replaced with TypedData_Wrap_Struct.

Files changed

  • rubysdl2_internal.h: DEFINE_DATA_TYPE macro, DEFINE_GETTER uses TypedData_Get_Struct
  • video.c.m4: Window, Renderer, Texture, Surface, DisplayMode, Rect, Point, FIELD_ACCESSOR macro
  • event.c: SDL_Event, EVENT_READER/EVENT_WRITER macros, all event type accessors
  • mixer.c.m4: Chunk, Music
  • ttf.c.m4: TTF
  • joystick.c.m4: Joystick
  • gamecontroller.c.m4: GameController
  • gl.c.m4: GLContext

Testing

  • Ruby 3.4.9: Builds with zero deprecation warnings, full functionality verified (window, renderer, TTF, mixer, events)
  • Ruby 3.3.9: Backward compatible, all functionality works

Replace all deprecated Data_Wrap_Struct/Data_Get_Struct with
TypedData_Wrap_Struct/TypedData_Get_Struct across all source files.

Add DEFINE_DATA_TYPE helper macro to rubysdl2_internal.h for easy
rb_data_type_t definition. Eliminates all deprecation warnings on
Ruby 3.4.x while maintaining backward compatibility with Ruby 3.3.x.

Files changed:
- rubysdl2_internal.h: DEFINE_DATA_TYPE macro, DEFINE_GETTER uses TypedData
- video.c.m4: Window, Renderer, Texture, Surface, DisplayMode, Rect, Point
- event.c: SDL_Event (EVENT_READER/EVENT_WRITER macros + all event types)
- mixer.c.m4: Chunk, Music
- ttf.c.m4: TTF
- joystick.c.m4: Joystick
- gamecontroller.c.m4: GameController
- gl.c.m4: GLContext

Closes #1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Owner

@ohai ohai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your PR.
It would be better to consider the following points.

Comment thread video.c.m4 Outdated
return Data_Make_Struct(klass, SDL_Point, 0, free, point);
SDL_Point* point = ALLOC(SDL_Point);
memset(point, 0, sizeof(SDL_Point));
return TypedData_Wrap_Struct(klass, &SDL_Point_data_type, point);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypedData_Make_Struct would be better.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Replaced ALLOC + TypedData_Wrap_Struct with TypedData_Make_Struct across all files (video.c.m4, event.c, mixer.c.m4, ttf.c.m4, joystick.c.m4, gamecontroller.c.m4, gl.c.m4). Updated in b9e2a39.

Comment thread rubysdl2_internal.h Outdated
*/
#define DEFINE_DATA_TYPE(struct_name, free_func) \
static const rb_data_type_t struct_name##_data_type = { \
#struct_name, \
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to have a suitable prefix like "ruby-sdl2/".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Added "ruby-sdl2/" prefix. The type name is now "ruby-sdl2/" #struct_name (e.g., "ruby-sdl2/Window"). Updated in b9e2a39.

Comment thread rubysdl2_internal.h Outdated
static const rb_data_type_t struct_name##_data_type = { \
#struct_name, \
{ NULL, (void (*)(void*))(free_func), NULL }, \
NULL, NULL, 0 \
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will RUBY_TYPED_FREE_IMMEDIATELY be better?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Changed from 0 to RUBY_TYPED_FREE_IMMEDIATELY. Updated in b9e2a39.

- Add "ruby-sdl2/" prefix to type names in DEFINE_DATA_TYPE macro
- Use RUBY_TYPED_FREE_IMMEDIATELY flag instead of 0
- Replace ALLOC + TypedData_Wrap_Struct with TypedData_Make_Struct

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Owner

@ohai ohai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code seems a bit loose to me.

Comment thread video.c.m4

return TypedData_Wrap_Struct(cRect, &SDL_Rect_data_type, rect);
SDL_Rect* rect;
VALUE obj = TypedData_Make_Struct(klass, SDL_Rect, &SDL_Rect_data_type, rect);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assigning to obj seems redundant. return TypedData_Make_Struct(...) looks sufficient.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply 4d153ad

Comment thread video.c.m4 Outdated
memset(point, 0, sizeof(SDL_Point));
return TypedData_Wrap_Struct(klass, &SDL_Point_data_type, point);
SDL_Point* point;
VALUE obj = TypedData_Make_Struct(klass, SDL_Point, &SDL_Point_data_type, point);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply 4d153ad

Comment thread video.c.m4
Renderer* r;
VALUE obj = TypedData_Make_Struct(cRenderer, Renderer, &Renderer_data_type, r);
r->renderer = renderer;
r->num_textures = 0;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply 9e08034

Comment thread video.c.m4
Window* w;
VALUE obj = TypedData_Make_Struct(cWindow, Window, &Window_data_type, w);
w->window = window;
w->num_renderers = 0;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove the line since TypedData_Make_Struct clears the allocated memory to zeros. However, removing this line will make the code unclear since other parts are explicitly initialized.

I think that this line should be kept.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply 9e08034

Return TypedData_Make_Struct directly instead of assigning to a
temporary variable in DisplayMode_s_allocate, Rect_s_allocate,
and Point_s_allocate where obj is not used before return.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TypedData_Make_Struct zero-clears allocated memory, but explicit
initialization of struct members (= 0, = NULL) serves as documentation
of what members exist and their expected initial values.

Restore removed initializations in Window_new, DisplayMode_s_allocate,
Renderer_new, Surface_new, and Rect_s_allocate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@takaokouji takaokouji requested a review from ohai April 4, 2026 11:54
@ohai
Copy link
Copy Markdown
Owner

ohai commented Apr 7, 2026

「since other parts are explicitly initialized」と言っているので 0 クリアだけで十分なのはそのままで良かったのですが。まあこれでOKです。

@ohai ohai merged commit e92eee2 into ohai:master Apr 7, 2026
@ohai
Copy link
Copy Markdown
Owner

ohai commented Apr 7, 2026

Thank you for your PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants