SDLRuby 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20bdcc86d9ea3a4670b1f0ac86689d0cae12f51417d9ba92cc710be1ecab8614
4
- data.tar.gz: 3869b91b982b18fe37c5dc97a4b7e99b9f42e2266b42957fa31632ce79bb3447
3
+ metadata.gz: fb651b451bbc9fc356e5f3a1ecb08d5855a690fa7b0556f7a9da5f0f11f2d6d4
4
+ data.tar.gz: 9f53754821bf14951f4cd014f1b776d07a5b3807a81ceee937ce96e6f71e148e
5
5
  SHA512:
6
- metadata.gz: e0c6372d9db1be4ffaa5ff4af4aba575d74d3c36682da3df5423c30fcde44c6986ebcd1b3c8d8e37a909148308922a98436cfba53ad75fcd91d6e84407d275bf
7
- data.tar.gz: fa71f7889d06990aed6fd43d8bd09573ca6900a7d7223ce513d0a47830610cc95f49a0883854d5d4670ccd7a67ca2e72576cf026298ad6bc94b08e70aecd2e6e
6
+ metadata.gz: f5cfbf90c23eb97fcec12e34af27a2966e7d5c3fc010186a28ff1ec2c4caaf5a5cefc0ed68863907f9dad417688b1ec9dc61388e4d4723fb199cfcf5b7582553
7
+ data.tar.gz: b91967cab249f58717362fa4d1241e650d0a38b54ff340167a631a76691a5a17811961fc675a9edfbd0ea8ff2259e4d9c0800c08999cf2273535091f529ce2b4
data/CHANGELOG.md CHANGED
@@ -1,6 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.2.0] - 2023-09-13
3
+ ## [0.3.1] - 2023-09-28
4
+ - Refactored RWOps class.
5
+
6
+ ## [0.3.0] - 2023-09-19
7
+ - Implemented Mouse Module.
8
+ - Implementation of the Timer Module.
9
+ - Implemented Keyboard Module.
10
+ - Specification and implementation of SDL.init, SDL.init?, and SDL.quit.
11
+
12
+ ## [0.2.1] - 2023-09-13
4
13
 
5
14
  - Memory leak fix on event retrieval failure.
6
15
 
@@ -3,56 +3,67 @@ module SDLRuby
3
3
  module_eval do
4
4
  num_keys = SDL.tmp_value("int")
5
5
 
6
- # SDL_GetKeyboardState() が戻すポインターはSDLがロードされた時点で作成されている。
7
- # この関数は SDL_Init() より前に呼ぶことができる。
6
+ # The SDL_GetKeyboardState function can be called before SDL_Init.
7
+ #
8
8
  ptr = SDL.SDL_GetKeyboardState(num_keys)
9
9
 
10
- # エラーになるのはnum_keysNULLを渡したとき。
10
+ # SDL_GetKeyboardState returns an error when num_keys is NULL.
11
+ #
11
12
  raise SDLError if ptr.null?
12
13
 
13
14
  ptr.size = num_keys.value
14
- @state = ptr
15
+ @ptr = ptr.freeze
15
16
  end
16
17
 
17
18
  class << self
18
- def [](idx)
19
- raise IndexError if idx < 0 || @state.size <= idx
20
- @state[idx] != 0
21
- end
22
-
23
- def any? = to_a.any?
24
-
25
- def clear = SDL.SDL_ResetKeyboard
26
-
27
- # キー名からキーコードを得る
28
- def keycode(s) = SDL.GetKeyFromName(s).nonzero?
19
+ include SDL
29
20
 
30
- # キーコードからキー名を得る
31
- def keycode_name(num)
32
- (s = SDL.GetKeyName(num).to_s).empty? ? nil : s
21
+ # This method specifies the ability to check for a match with
22
+ # the characters appearing in the 'when' clause of a 'case' statement.
23
+ #
24
+ # see also: String#===
25
+ #
26
+ def ==(other)
27
+ case other
28
+ when Integer
29
+ 0 <= other && other < @ptr.size && @ptr[other] != 0
30
+ when String, Symbol
31
+ (idx = scancode(other)) != 0 && @ptr[idx] != 0
32
+ else
33
+ super
34
+ end
33
35
  end
34
36
 
35
- # 修飾キーの状態を得る
36
- def mod
37
- SDL.SDL_GetModState #=> integer
37
+ def any?
38
+ # SDL sets a byte to either 0x00 or 0x01 for each scancode.
39
+ # It does not fill the byte sequence with 0x80, so this should work.
40
+ #
41
+ to_str.sum != 0
38
42
  end
39
43
 
40
- # 修飾キーを設定する
41
- def mod=(modstate)
42
- SDL.SDL_SetModState(modstate)
44
+ def clear
45
+ # SDL_ResetKeyboard should be preceded by initializing SDL events since
46
+ # it sends SDLK_KEYUP events for pressed keys.
47
+ #
48
+ # Calling SDL_ResetKeyboard when the SDL event subsystem is not initialized
49
+ # results in a core dump.
50
+ #
51
+ SDL.SDL_ResetKeyboard if SDL.init?(SDL_INIT_EVENTS)
43
52
  end
44
53
 
45
- # キー名からスキャンコードを得る
46
- def scancode(s) = SDL.GetScancodeFromName(s).nonzero?
54
+ def mod = SDL.SDL_GetModState
47
55
 
48
- # スキャンコードからキー名を得る
49
- def scancode_name(num)
50
- (s = SDL.GetScancodeName(num).to_s).empty? ? nil : s
51
- end
56
+ def scancode(s) = SDL.SDL_GetScancodeFromName(s.to_s)
57
+
58
+ def scancode_name(num) = SDL.SDL_GetScancodeName(num).to_s
59
+
60
+ def size = @ptr.size
61
+
62
+ alias length size
52
63
 
53
- def to_a = to_str.unpack("C*").map(&:nonzero?)
64
+ def to_a = size.times.select { |i| @ptr[i] != 0 }
54
65
 
55
- def to_str = @state.to_str
66
+ def to_str = @ptr.to_str
56
67
  end
57
68
  end
58
69
  end
data/lib/SDLRuby/mouse.rb CHANGED
@@ -1,52 +1,130 @@
1
1
  module SDLRuby
2
2
  module Mouse
3
- @global_x, @global_y = *SDL.tmp_value("int", "int")
4
- @relative_x, @relative_y = *SDL.tmp_value("int", "int")
5
- @x, @y = *SDL.tmp_value("int", "int")
6
-
7
3
  class << self
8
4
  include SDL
9
5
 
10
- def to_button_ary(num)
11
- [
12
- num & SDL_BUTTON_LMASK != 0,
13
- num & SDL_BUTTON_MMASK != 0,
14
- num & SDL_BUTTON_RMASK != 0,
15
- num & SDL_BUTTON_X1MASK != 0,
16
- num & SDL_BUTTON_X2MASK != 0
17
- ]
18
- end
6
+ def button = button_to_ary(WindowMouse.button)
19
7
 
8
+ # If called without initializing the SDL video subsystem,
9
+ # even if a mouse is present in the system, it will return an error.
10
+ #
11
+ # This method must be called from the main thread.
12
+ #
20
13
  def capture=(b)
21
14
  err = SDL.SDL_CaptureMouse(b ? 1 : 0)
22
15
  raise SDLError if err < 0
23
16
  end
24
17
 
18
+ def global_button = button_to_ary(GlobalMouse.button)
19
+
20
+ def global_pos = GlobalMouse.pos
21
+
22
+ # If called without initializing the SDL video subsystem,
23
+ # even if a mouse is present in the system, it will return an error.
24
+ #
25
25
  def global_pos=(xy)
26
- err = SDL.SDL_WarpMouseGlobal(*xy)
27
- raise SDLError if err < 0
26
+ GlobalMouse.pos=(xy)
28
27
  end
29
28
 
30
- def global_state = [
31
- SDL.SDL_GetGlobalMouseState(@global_x, @global_y),
32
- @global_x.value, @global_y.value
33
- ]
29
+ def global_state
30
+ a = GlobalMouse.state
31
+ a[0] = button_to_ary(a[0])
32
+ a
33
+ end
34
34
 
35
+ def pos = WindowMouse.pos
36
+
37
+ def pos=(xy)
38
+ SDL.SDL_WarpMouseInWindow(nil, *xy)
39
+ end
40
+
41
+ # If called without initializing the SDL video subsystem,
42
+ # even if a mouse is present in the system, it will return an error.
43
+ #
35
44
  def relative=(b)
36
45
  err = SDL.SDL_SetRelativeMouseMode(b ? 1 : 0)
37
46
  raise SDLError if err < 0
38
47
  end
39
48
 
40
- def relative? = SDL.SDL_GetRelativeMouseMode == 1
49
+ def relative? = SDL.SDL_GetRelativeMouseMode != 0
50
+
51
+ def relative_pos = RelativeMouse.pos
52
+
53
+ def relative_state
54
+ a = RelativeMouse.state
55
+ a[0] = button_to_ary(a[0])
56
+ a
57
+ end
58
+
59
+ def state
60
+ a = WindowMouse.state
61
+ a[0] = button_to_ary(a[0])
62
+ a
63
+ end
64
+
65
+ private
66
+
67
+ def button_to_ary(num)
68
+ [
69
+ num & SDL_BUTTON_LMASK != 0,
70
+ num & SDL_BUTTON_MMASK != 0,
71
+ num & SDL_BUTTON_RMASK != 0,
72
+ num & SDL_BUTTON_X1MASK != 0,
73
+ num & SDL_BUTTON_X2MASK != 0,
74
+ ]
75
+ end
76
+ end
77
+
78
+ module GlobalMouse
79
+ @x, @y = SDL.tmp_value("int", "int")
80
+
81
+ class << self
82
+ def button = SDL.SDL_GetGlobalMouseState(nil, nil)
41
83
 
42
- def relative_state = [
43
- SDL.SDL_GetRelativeMouseState(@relative_x, @relative_y),
44
- @relative_x.value, @relative_y.value
45
- ]
84
+ def pos
85
+ SDL.SDL_GetGlobalMouseState(@x, @y)
86
+ [@x.value, @y.value]
87
+ end
46
88
 
47
- def state = [
48
- SDL.SDL_GetMouseState(@x, @y), @x.value, @y.value
49
- ]
89
+ def pos=(xy)
90
+ err = SDL.SDL_WarpMouseGlobal(*xy)
91
+ raise SDLError if err < 0
92
+ end
93
+
94
+ def state = [SDL.SDL_GetGlobalMouseState(@x, @y), @x.value, @y.value]
95
+ end
96
+ end
97
+
98
+ module RelativeMouse
99
+ @x, @y = SDL.tmp_value("int", "int")
100
+
101
+ class << self
102
+ def pos
103
+ SDL.SDL_GetRelativeMouseState(@x, @y)
104
+ [@x.value, @y.value]
105
+ end
106
+
107
+ def state = [SDL.SDL_GetRelativeMouseState(@x, @y), @x.value, @y.value]
108
+ end
109
+ end
110
+
111
+ module WindowMouse
112
+ @x, @y = SDL.tmp_value("int", "int")
113
+
114
+ class << self
115
+ def button = SDL.SDL_GetMouseState(nil, nil)
116
+
117
+ def pos
118
+ SDL.SDL_GetMouseState(@x, @y)
119
+ [@x.value, @y.value]
120
+ end
121
+
122
+ def pos=(xy)
123
+ SDL.SDL_WarpMouseInWindow(nil, *xy)
124
+ end
125
+
126
+ def state = [SDL.SDL_GetMouseState(@x, @y), @x.value, @y.value]
127
+ end
50
128
  end
51
129
  end
52
130
  end
@@ -0,0 +1,116 @@
1
+ module SDLRuby
2
+ class RW
3
+ module Operational
4
+ def close
5
+ unless closed?
6
+ err = SDL.SDL_RWclose(to_ptr)
7
+
8
+ raise SDLError if err < 0
9
+ end
10
+ end
11
+
12
+ def closed? = to_ptr.freed?
13
+
14
+ def eof?
15
+ raise SDLError, "closed and freed rw" if closed?
16
+
17
+ s = SDL.SDL_RWsize(to_ptr)
18
+ raise SDLError if s < 0
19
+
20
+ t = SDL.SDL_RWtell(to_ptr)
21
+ raise SDLError if t < 0
22
+
23
+ s == t
24
+ end
25
+
26
+ def read(length = nil, buffer = nil)
27
+ raise SDLError, "closed and freed rw" if closed?
28
+
29
+ if length.nil?
30
+ len = size - tell
31
+ else
32
+ len = Integer.try_convert(length)
33
+ if len.nil?
34
+ raise TypeError,
35
+ "no implicit conversion of #{length.class} into Integer"
36
+ end
37
+ end
38
+
39
+ if len < 0
40
+ raise ArgumentError, "negative length #{len} given"
41
+ end
42
+
43
+ if buffer.nil?
44
+ buffer = ""
45
+ else
46
+ buffer = String.try_convert(buffer)
47
+ if buffer.nil?
48
+ raise TypeError,
49
+ "no implicit conversion of #{buffer.class} into String"
50
+ end
51
+ end
52
+
53
+ if eof? || len == 0
54
+ buffer.clear
55
+ return len == 0 ? buffer : nil
56
+ end
57
+
58
+ bytesize = buffer.bytesize
59
+ if len == bytesize
60
+ buffer
61
+ elsif len > bytesize
62
+ buffer.gsub!(/\z/nm, "\x00" * (len - bytesize))
63
+ elsif len < bytesize
64
+ buffer.gsub!(/[\x00-\xFF]{#{bytesize - len}}\z/nm, "")
65
+ end
66
+
67
+ n = SDL.SDL_RWread(to_ptr, buffer, 1, len)
68
+ if n < len
69
+ buffer.gsub!(/[\x00-\xFF]{#{n}}$/nm, "")
70
+ end
71
+ raise SDLError if n == 0
72
+
73
+ buffer
74
+ end
75
+
76
+ def seek(offset, whence = IO::SEEK_SET)
77
+ raise SDLError, "closed and freed rw" if closed?
78
+
79
+ n = SDL.SDL_RWseek(to_ptr, offset, whence)
80
+ raise SDLError if n < 0
81
+ 0
82
+ end
83
+
84
+ alias pos= seek
85
+
86
+ def size
87
+ raise SDLError, "closed and freed rw" if closed?
88
+
89
+ n = SDL.SDL_RWsize(to_ptr)
90
+ raise SDLError if n < 0
91
+ n
92
+ end
93
+
94
+ def tell
95
+ raise SDLError, "closed and freed rw" if closed?
96
+
97
+ n = SDL.SDL_RWtell(to_ptr)
98
+ raise SDLError if n < 0
99
+ n
100
+ end
101
+
102
+ alias pos tell
103
+
104
+ def write(obj)
105
+ raise SDLError, "closed and freed rw" if closed?
106
+
107
+ ptr = obj.to_s
108
+ len = ptr.bytesize
109
+
110
+ n = SDL.SDL_RWwrite(to_ptr, ptr, 1, len)
111
+ raise SDLError if n < len
112
+ n
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,28 @@
1
+ module SDLRuby
2
+ class RW
3
+ class ReadClosure < Fiddle::Closure
4
+ include Fiddle
5
+
6
+ def initialize(obj)
7
+ # size_t (*read) (SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
8
+ #
9
+ super(TYPE_SIZE_T, [TYPE_VOIDP, TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T])
10
+ @obj = obj
11
+ end
12
+
13
+ def call(_, ptr, size, maxnum)
14
+ len = size * maxnum
15
+ return 0 if len.zero?
16
+
17
+ s = @obj.read(len)
18
+ return 0 if s.nil? || s.empty? # EOF
19
+
20
+ ptr[0, s.size] = s
21
+ s.size / size
22
+ rescue => e
23
+ SDL.last_error_message = e.message
24
+ 0
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ module SDLRuby
2
+ class RW
3
+ class SeekClosure < Fiddle::Closure
4
+ include Fiddle
5
+
6
+ def initialize(obj)
7
+ # Sint64 (*seek) (SDL_RWops *context, Sint64 offset, int whence)
8
+ #
9
+ super(TYPE_INT64_T, [TYPE_VOIDP, TYPE_INT64_T, TYPE_INT])
10
+ @obj = obj
11
+ end
12
+
13
+ def call(_, offset, whence)
14
+ @obj.seek(offset, whence)
15
+ @obj.tell
16
+ rescue => e
17
+ SDL.last_error_message = e.message
18
+ -1
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module SDLRuby
2
+ class RW
3
+ class SizeClosure < Fiddle::Closure
4
+ include Fiddle
5
+
6
+ def initialize(obj)
7
+ # Sint64 (*size) (SDL_RWops *context)
8
+ #
9
+ super(TYPE_INT64_T, [TYPE_VOIDP])
10
+ @obj = obj
11
+ end
12
+
13
+ def call(_)
14
+ @obj.size
15
+ rescue => e
16
+ SDL.last_error_message = e.message
17
+ -1
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module SDLRuby
2
+ class RW
3
+ class WriteClosure < Fiddle::Closure
4
+ include Fiddle
5
+
6
+ def initialize(obj)
7
+ # size_t (*write) (SDL_RWops *context, const void *ptr, size_t size, size_t num)
8
+ #
9
+ super(TYPE_SIZE_T, [TYPE_VOIDP, TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T])
10
+ @obj = obj
11
+ end
12
+
13
+ def call(_, ptr, size, num)
14
+ @obj.write(ptr.to_str(size * num)) / size
15
+ rescue => e
16
+ SDL.last_error_message = e.message
17
+ 0
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ module SDLRuby
2
+ class RWOps
3
+ include Fiddle, SDL
4
+
5
+ # これはSDL3では不要になります。
6
+ # SDL3ではメンバーの関数ポインターにNULLを設定できます。
7
+ # それは”適切な”デフォルトの動作を意味します。
8
+ #
9
+ #
10
+ #
11
+ # SDL2ではcloseにはC関数ポインターを設定する必要がある。
12
+ # Rubyのクロージャ―を設定するとGCが動作時に該当のクロージャ―が既に回収されているため
13
+ # コアダンプする。
14
+ # また、NULLに設定するとSDL_RWclose関数の呼び出し時にコアダンプする。
15
+ # ここではSDLをハックしてmem_close関数を割り当てた。
16
+ # この関数は内部でSDL_FreeRW関数を呼び出すだけである。
17
+ #
18
+ # int (*close) (SDL_RWops *context)
19
+ #
20
+ MEM_CLOSE = module_eval do
21
+ ptr = Pointer.malloc(1, RUBY_FREE)
22
+ rw = SDL.SDL_RWFromMem(ptr, ptr.size)
23
+ raise SDLError if rw.null?
24
+ SDL_RWops.new(rw, SDL_FREE_RW)["close"].to_int
25
+ end
26
+ end
27
+ end
@@ -1,128 +1,34 @@
1
- module SDLRuby
2
- class RWOps
3
- class RWObject
4
- include Fiddle, SDL
5
-
6
- # size_t (*read) (SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
7
- #
8
- class ReadClosure < Fiddle::Closure
9
- include Fiddle
10
-
11
- def initialize(obj)
12
- super(TYPE_SIZE_T, [TYPE_VOIDP, TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T])
13
- @obj = obj
14
- end
15
-
16
- def call(_, ptr, size, maxnum)
17
- len = size * maxnum
18
- return 0 if len.zero?
19
-
20
- s = @obj.read(len)
21
- return 0 if s.nil? || s.empty? # EOF
22
-
23
- ptr[0, s.size] = s
24
- s.size / size
25
- rescue => e
26
- SDL.last_error_message = e.full_message
27
- 0
28
- end
29
- end
30
-
31
- # Sint64 (*seek) (SDL_RWops *context, Sint64 offset, int whence)
32
- #
33
- class SeekClosure < Fiddle::Closure
34
- include Fiddle
35
-
36
- def initialize(obj)
37
- super(TYPE_INT64_T, [TYPE_VOIDP, TYPE_INT64_T, TYPE_INT])
38
- @obj = obj
39
- end
40
-
41
- def call(_, offset, whence)
42
- @obj.seek(offset, whence)
43
- @obj.tell
44
- rescue => e
45
- SDL.last_error_message = e.full_message
46
- -1
47
- end
48
- end
49
-
50
- # Sint64 (*size) (SDL_RWops *context)
51
- #
52
- class SizeClosure < Fiddle::Closure
53
- include Fiddle
54
-
55
- def initialize(obj)
56
- super(TYPE_INT64_T, [TYPE_VOIDP])
57
- @obj = obj
58
- end
59
-
60
- def call(_)
61
- @obj.size
62
- rescue => e
63
- raise e if $DEBUG
64
- SDL.last_error_message = e.full_message
65
- -1
66
- end
67
- end
68
-
69
- # size_t (*write) (SDL_RWops *context, const void *ptr, size_t size, size_t num)
70
- #
71
- class WriteClosure < Fiddle::Closure
72
- include Fiddle
73
-
74
- def initialize(obj)
75
- super(TYPE_SIZE_T, [TYPE_VOIDP, TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T])
76
- @obj = obj
77
- end
78
-
79
- def call(_, ptr, size, num)
80
- @obj.write(ptr.to_str(size * num)) / size
81
- rescue => e
82
- SDL.last_error_message = e.full_message
83
- 0
84
- end
85
- end
86
-
87
- # closeにはC関数を設定する必要がある。
88
- # クロージャ―を設定するとGCによる回収の際に
89
- # 該当のクロージャ―が既に回収されているためコアダンプする。
90
- # また、NULLに設定するとSDL_RWclose関数の呼び出し時にコアダンプする。
91
- # SDLをハックしてmem_close関数を割り当てた。
92
- # この関数は内部でSDL_FreeRW関数を呼び出すだけである。
93
- #
94
- # int (*close) (SDL_RWops *context)
95
- #
96
- MEM_CLOSE = module_eval do
97
- _ptr = Pointer.malloc(1, RUBY_FREE)
98
- rw = SDL.SDL_RWFromMem(_ptr, _ptr.size)
99
- raise SDLError if rw.null?
100
- st = SDL_RWops.new(rw)
101
-
102
- st.close.freeze
103
- end
104
-
105
- # 引数 obj に与えたオブジェクトは SDL から close を呼び出されてもクローズしない。
106
- # このインスタンスを単独で扱う場合は使い終わったらclose関数を呼び出す必要がある。
107
- # そうしなければポインターは開放されずメモリーリークする。
108
- #
109
- def initialize(obj)
110
- ptr = SDL.SDL_AllocRW
111
- raise SDLError if ptr.null?
112
-
113
- # SDLではSDL_RWopsポインターの開放はclose関数から行うように実装されている。
114
- # これと同じ仕様とするため、このインスタンスではfreeの設定を行わない。
115
- #
116
- @st = SDL_RWops.new(ptr)
117
-
118
- @st.close = MEM_CLOSE
119
- @st.read = @read = ReadClosure.new(obj)
120
- @st.seek = @seek = SeekClosure.new(obj)
121
- @st.size = @size = SizeClosure.new(obj)
122
- @st.write = @write = WriteClosure.new(obj)
123
- end
124
-
125
- def to_ptr = @st.to_ptr
126
- end
127
- end
128
- end
1
+ require_relative '../rw/read_closure'
2
+ require_relative '../rw/seek_closure'
3
+ require_relative '../rw/size_closure'
4
+ require_relative '../rw/write_closure'
5
+ require_relative 'mem_close'
6
+
7
+ module SDLRuby
8
+ class RWOps
9
+ class RWObject
10
+ include Fiddle, SDL
11
+
12
+ # 引数objに与えたオブジェクトはSDLからcloseを呼び出されてもクローズしない。
13
+ # このインスタンスを単独で扱う場合は使い終わったらclose関数を呼び出す必要がある。
14
+ # そうしなければポインターは開放されずメモリーリークする。
15
+ #
16
+ def initialize(obj)
17
+ ptr = SDL.SDL_AllocRW
18
+ raise SDLError if ptr.null?
19
+
20
+ @st = SDL_RWops.new(ptr)
21
+
22
+ # SDLではSDL_RWopsポインターの開放はclose関数ポインターを呼び出して行う仕様となっている。
23
+ #
24
+ @st.close = MEM_CLOSE
25
+ @st.read = @read = RW::ReadClosure.new(obj)
26
+ @st.seek = @seek = RW::SeekClosure.new(obj)
27
+ @st.size = @size = RW::SizeClosure.new(obj)
28
+ @st.write = @write = RW::WriteClosure.new(obj)
29
+ end
30
+
31
+ def to_ptr = @st.to_ptr
32
+ end
33
+ end
34
+ end