SDLRuby 0.2.1 → 0.3.1

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 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