nice-ffi 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,44 @@
1
+ ------------------------------------------------------------
2
+ Author: John Croisant <jacius@gmail.com>
3
+ Date: Wed Mar 31 17:57:44 2010 -0500
4
+
5
+ Nice-FFI 0.4 released.
6
+
7
+ M README.rdoc
8
+ M nice-ffi.gemspec
9
+
10
+ ------------------------------------------------------------
11
+ Author: John Croisant <jacius@gmail.com>
12
+ Date: Tue Mar 9 23:08:31 2010 -0600
13
+
14
+ Fixed PathSet not expanding globs (like "*").
15
+
16
+ M lib/nice-ffi/pathset.rb
17
+
18
+ ------------------------------------------------------------
19
+ Author: John Croisant <jacius@gmail.com>
20
+ Date: Sat Jan 30 02:52:27 2010 -0600
21
+
22
+ Fixed PathSet failing when a path doesn't end with a separator.
23
+
24
+ M lib/nice-ffi/pathset.rb
25
+
26
+ ------------------------------------------------------------
27
+ Author: John Croisant <jacius@gmail.com>
28
+ Date: Wed Jan 27 16:08:51 2010 -0600
29
+
30
+ Fixed DEFAULT_PATHS -> DEFAULT in library.rb.
31
+
32
+ M lib/nice-ffi/library.rb
33
+
34
+ ------------------------------------------------------------
35
+ Author: John Croisant <jacius@gmail.com>
36
+ Date: Mon Jan 18 00:14:29 2010 -0600
37
+
38
+ Better globs for rdoc rake task.
39
+
40
+ M Rakefile
41
+
1
42
  ------------------------------------------------------------
2
43
  Author: John Croisant <jacius@gmail.com>
3
44
  Date: Sun Jan 17 21:04:08 2010 -0600
@@ -1,8 +1,8 @@
1
1
 
2
2
  = Nice-FFI
3
3
 
4
- Version:: 0.3
5
- Date:: 2010-01-17
4
+ Version:: 0.4
5
+ Date:: 2010-03-31
6
6
 
7
7
  Homepage:: http://github.com/jacius/nice-ffi/
8
8
  Author:: John Croisant <jacius@gmail.com>
@@ -65,7 +65,7 @@ module NiceFFI::Library
65
65
  #
66
66
  # Raises LoadError if it could not find or load the library.
67
67
  #
68
- def load_library( names, search_paths=NiceFFI::PathSet::DEFAULT_PATHS )
68
+ def load_library( names, search_paths=NiceFFI::PathSet::DEFAULT )
69
69
 
70
70
  names = [names] unless names.kind_of? Array
71
71
 
@@ -465,8 +465,8 @@ class NiceFFI::PathSet
465
465
  results = paths.collect do |path|
466
466
  files.collect do |file|
467
467
  names.collect do |name|
468
- # Concat path and file, fill in for [NAME], and expand.
469
- File.expand_path( (path+file).gsub("[NAME]", name) )
468
+ # Join path and file, fill in for [NAME], expand, and unglob.
469
+ Dir[ File.expand_path( File.join(path,file).gsub("[NAME]",name) ) ]
470
470
  end
471
471
  end
472
472
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nice-ffi
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.3"
4
+ version: "0.4"
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Croisant
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-17 00:00:00 -06:00
12
+ date: 2010-03-31 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -34,9 +34,6 @@ extensions: []
34
34
  extra_rdoc_files: []
35
35
 
36
36
  files:
37
- - pkg/nice-ffi-0.2/docs/usage.rdoc
38
- - pkg/nice-ffi-0.2/TODO.rdoc
39
- - pkg/nice-ffi-0.2/README.rdoc
40
37
  - docs/usage.rdoc
41
38
  - TODO.rdoc
42
39
  - README.rdoc
@@ -1,88 +0,0 @@
1
-
2
- = Nice-FFI
3
-
4
- Version:: 0.2
5
- Date:: 2009-10-24
6
-
7
- Homepage:: http://github.com/jacius/nice-ffi/
8
- Author:: John Croisant <jacius@gmail.com>
9
- Copyright:: 2009 John Croisant
10
-
11
-
12
- == Description
13
-
14
- Nice-FFI is a layer on top of Ruby-FFI [1] (and compatible FFI
15
- systems) with features to ease development of FFI-based libraries.
16
-
17
- Nice-FFI currently features:
18
-
19
- * NiceFFI::Library: a stand-in for FFI::Library that provides methods
20
- for easily finding and loading libraries on any platform, plus
21
- automatic wrapping of functions that return struct pointers.
22
-
23
- * NiceFFI::PathSet: a class with customizable rules for finding
24
- library files on multiple operating system. PathSet is used by
25
- NiceFFI::Library.load_library.
26
-
27
- * NiceFFI::Struct: a stand-in for FFI::Struct that provides automatic
28
- accessors for struct members, optional automatic memory management,
29
- more instance initialization options, pretty to_s and inspect
30
- methods, and other niceties.
31
-
32
- * NiceFFI::OpaqueStruct: a base class for structs with no user-exposed
33
- members. Useful when the struct definition is hidden by the
34
- underlying C library.
35
-
36
- Nice-FFI was originally developed as part of Ruby-SDL-FFI [2].
37
-
38
- 1. Ruby-FFI: http://github.com/ffi/ffi
39
- 2. Ruby-SDL-FFI: http://github.com/jacius/ruby-sdl-ffi/
40
-
41
-
42
- == Caveats
43
-
44
- Nice-FFI is still in EARLY DEVELOPMENT STAGES. That means:
45
-
46
- * It may not work correctly (or at all).
47
- * It may not be complete.
48
- * It may change drastically with no advanced notice.
49
-
50
- As such, this library is currently FOR THE ADVENTUROUS ONLY.
51
- If you are not willing to continuously update your code to
52
- match the new API, then you should wait until version 1.0.
53
-
54
-
55
- == Requirements
56
-
57
- * Ruby-FFI >= 0.4.0 (or compatible FFI implementation)
58
-
59
-
60
- == Usage
61
-
62
- See docs/usage.rdoc for usage information.
63
-
64
-
65
- == License
66
-
67
- Nice-FFI is licensed under the following terms (the "MIT License"):
68
-
69
- Copyright (c) 2009 John Croisant
70
-
71
- Permission is hereby granted, free of charge, to any person obtaining
72
- a copy of this software and associated documentation files (the
73
- "Software"), to deal in the Software without restriction, including
74
- without limitation the rights to use, copy, modify, merge, publish,
75
- distribute, sublicense, and/or sell copies of the Software, and to
76
- permit persons to whom the Software is furnished to do so, subject to
77
- the following conditions:
78
-
79
- The above copyright notice and this permission notice shall be
80
- included in all copies or substantial portions of the Software.
81
-
82
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
83
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
84
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
85
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
86
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
87
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
88
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,16 +0,0 @@
1
-
2
- = TODO
3
-
4
- * Struct
5
- * Write accessor for nested structs (not struct pointers).
6
- See comment in NiceFFI::Struct._make_writer for details.
7
-
8
- * Specs
9
- * Library (use a mock for ffi_lib.)
10
- * PathSet#find (use a mock for File.exist?.)
11
- * Struct
12
- * TypedPointer
13
-
14
- * Better documentation comments
15
- * Library#attach_function
16
- * Library#load_library
@@ -1,361 +0,0 @@
1
- = Using Nice-FFI
2
-
3
- This is a guide on how to use Nice-FFI's features. It assumes that you
4
- are already somewhat familiar with Ruby-FFI.
5
-
6
-
7
- == NiceFFI::Library
8
-
9
- NiceFFI::Library is a drop-in replacement for FFI::Library. It provides
10
- improved library finding abilities and support for TypedPointer return
11
- types for attached functions.
12
-
13
-
14
- In fact, NiceFFI::Library *is* FFI::Library, but with a few extras.
15
- That means that you can do all the regular FFI::Library stuff as well
16
- as the stuff described here.
17
-
18
-
19
- === load_library
20
-
21
- NiceFFI::Library.load_library is a more convenient replacement for
22
- FFI::Library.ffi_lib. It uses NiceFFI::PathSet to search for the
23
- library in the most likely places, depending on the user's operating
24
- system. For example, on Linux it would look for "lib[NAME].so" in
25
- "/usr/lib/" (among others), while on Windows it would look for
26
- "[NAME].dll" in "C:\windows\system32\".
27
-
28
- Using load_library is easy. Just use "extend NiceFFI::Library" instead
29
- of "extend FFI::Library", and use "load_library" instead of "ffi_lib":
30
-
31
-
32
- require 'nice-ffi'
33
-
34
- module MyLibraryModule
35
- extend NiceFFI::Library
36
-
37
- load_library("SDL") # look for libSDL.so, SDL.dll, etc.
38
-
39
- # structs, functions, etc. as usual.
40
-
41
- end
42
-
43
-
44
- ==== Advanced load_library
45
-
46
- As mentioned, load_library uses NiceFFI::PathSet to search for the
47
- library in likely directories. Specifically, it looks for:
48
-
49
-
50
- paths = {
51
- /linux|bsd/ => [ "/usr/local/lib/",
52
- "/usr/lib/" ],
53
-
54
- /darwin/ => [ "/usr/local/lib/",
55
- "/sw/lib/",
56
- "/opt/local/lib/",
57
- "~/Library/Frameworks/",
58
- "/Library/Frameworks/" ],
59
-
60
- /windows/ => [ "C:\\windows\\system32\\",
61
- "C:\\windows\\system\\" ]
62
- }
63
-
64
- files = {
65
- /linux|bsd/ => [ "lib[NAME].so" ],
66
-
67
- /darwin/ => [ "lib[NAME].dylib",
68
- "[NAME].framework/[NAME]" ],
69
-
70
- /windows/ => [ "[NAME].dll" ]
71
- }
72
-
73
- NiceFFI::PathSet::DEFAULT = NiceFFI::PathSet.new( paths, files )
74
-
75
-
76
- The paths hash tells PathSet where to look for libraries, and the
77
- files hash tells it the format of the library filename itself. The
78
- string "[NAME]" is replaced with whatever string you pass to
79
- load_library.
80
-
81
- Each key in the hash should be a Regexp that matches an OS name from
82
- FFI::Platform::OS. As of this writing (October 2009), the list of
83
- recognized OS names is:
84
-
85
- * "darwin" (MacOS X)
86
- * "freebsd"
87
- * "linux"
88
- * "openbsd"
89
- * "solaris"
90
- * "windows"
91
-
92
- So, if the user is running Linux and you try to load "SDL", it will
93
- first look for "/usr/local/lib/libSDL.so". If it can't find that, it
94
- will then look for "/usr/lib/libSDL.so". It would also use those same
95
- paths for FreeBSD or OpenBSD, because those OS names also match the
96
- regexp /linux|bsd/.
97
-
98
- If the library could not be found in any of the given directories with
99
- the given file name formats, load_library will just try loading "SDL"
100
- using ffi_lib (which does some platform-appropriate guesses too). If
101
- that fails too, LoadError is raised.
102
-
103
- If you want to load from a different path, you can make a custom
104
- PathSet and pass it to load_library:
105
-
106
-
107
- libs_dir = File.dirname(__FILE__) + "/libs/"
108
-
109
- pathset = NiceFFI::PathSet::DEFAULT.prepend( libs_dir )
110
-
111
- load_library( "SDL", my_pathset )
112
-
113
-
114
- The above example prepends (adds in front) the new paths so
115
- that load_library will look for the library in "./libs/" first.
116
- See PathSet for other useful methods for modifying PathSets.
117
-
118
-
119
- Another advanced usage tip: If a library has several alternative
120
- names, you can provide an Array of names:
121
-
122
-
123
- # It might be called "foo", "foo2", or "Foo".
124
-
125
- load_library( ["foo", "foo2", "Foo"] )
126
-
127
-
128
- === attach_function
129
-
130
- NiceFFI::Library#attach_function behaves similarly to
131
- FFI::Library#attach_function, except it supports TypedPointer return
132
- values. For example, suppose you have a C function:
133
-
134
-
135
- MyStruct *make_my_struct( int x, int y );
136
-
137
-
138
- This returns a pointer to an instance of MyStruct. With FFI, you'd
139
- write this to attach it:
140
-
141
-
142
- attach_function :make_my_struct, [:int, :int], :pointer
143
-
144
-
145
- And when you called it, it would return an FFI::Pointer, which you
146
- would then have to manually wrap every time you called the method:
147
-
148
-
149
- ptr = make_my_struct( 1, 2 )
150
- mystruct = MyStruct.new( ptr )
151
-
152
-
153
- With TypedPointer, the wrapping happens automatically. Just attach
154
- the function with a TypedPointer instead of :pointer:
155
-
156
-
157
- attach_function :make_my_struct, [:int, :int], NiceFFI::TypedPointer( MyStruct )
158
-
159
- # If MyStruct is based on NiceFFI::Struct, you can do this instead:
160
-
161
- attach_function :make_my_struct, [:int, :int], MyStruct.typed_pointer
162
-
163
-
164
- Then you automatically get a MyStruct instance when you call the function:
165
-
166
-
167
- mystruct = make_my_struct( 1, 2 )
168
- mystruct.instance_of?( MyStruct ) # => Heck yeah it sure is!
169
-
170
-
171
- Voila!
172
-
173
-
174
- == NiceFFI::Struct
175
-
176
- NiceFFI::Struct is a replacement for FFI::Struct. It provides several
177
- features in addition to the normal FFI::Struct behavior:
178
-
179
- * Ability to construct new instances from Array, Hash, another instance,
180
- or a pointer as usual.
181
- * Automatic read and write accessors for struct members.
182
- * Accessors for struct pointer members with TypedPointer.
183
- * Ability to dump an instance as an Array (#to_ary) or Hash (#to_hash).
184
- * Pretty and useful #to_s and #inspect for debugging.
185
-
186
-
187
- === Constructors
188
-
189
- NiceFFI::Struct allows you to construct a new struct instance from
190
- a Hash, Array, or another existing instance of the same struct type.
191
- It can also accept a pointer, just as with FFI::Struct.
192
-
193
-
194
- class MyStruct < NiceFFI::Struct
195
- layout :x, :int,
196
- :y, :int
197
- end
198
-
199
- mystruct = MyStruct.new( {:x => 1, :y => 2} ) # from Hash
200
- mystruct2 = MyStruct.new( [1,2] ) # from Array
201
- mystruct3 = MyStruct.new( mystruct ) # from another instance
202
- mystruct4 = MyStruct.new( ptr ) # from Pointer
203
-
204
-
205
- === Struct Member Accessors
206
-
207
- Struct members are defined automatically when you use
208
- NiceFFI::Struct.layout:
209
-
210
-
211
- class MyStruct < NiceFFI::Struct
212
- layout :x, :int,
213
- :y, :int
214
- end
215
-
216
- mystruct = MyStruct.new({:x => 1, :y => 2})
217
-
218
- mystruct.x # => 1
219
- mystruct.y # => 2
220
-
221
- mystruct.x = 3
222
- mystruct.y = -4
223
-
224
-
225
- Sometimes a struct will have members that should be read-only,
226
- or completely hidden. In those cases, you can use
227
- NiceFFI::Struct.read_only and NiceFFI::Struct.hidden.
228
-
229
-
230
- class MySneakyStruct < NiceFFI::Struct
231
- layout :readme, :int,
232
- :readme2, :int,
233
- :hideme, :pointer,
234
- :hideme2, :pointer,
235
- :normal, :uint32
236
-
237
- read_only :readme, :readme2
238
- hidden :hideme, :hideme2
239
- end
240
-
241
- sneaky = MySneakyStruct.new( ... )
242
-
243
-
244
- read_only prevents a write accessor from being created (or removes
245
- it if there is already one). hidden does the same, but for both
246
- read and write accessors. hidden also prevents the member from
247
- being shown in #to_s and #inspect.
248
-
249
- read_only and hidden can go before or after layout (or both),
250
- and you can safely call them multiple times if you need to.
251
-
252
-
253
- === TypedPointer Struct Member Accessors
254
-
255
- Some struct members are :pointers that point to other structs.
256
- With FFI::Struct, you'd have to manually wrap and unwrap the
257
- struct pointer, but if you specify a TypedPointer instead of
258
- :pointer, NiceFFI::Struct will wrap and unwrap it automatically:
259
-
260
-
261
- class StructWithPtr < NiceFFI::Struct
262
- layout :x, :int,
263
- :y, :int,
264
- :my, NiceFFI::TypedPointer( MyStruct )
265
- end
266
-
267
- struct = StructWithPtr.new( :x => -1,
268
- :y => -2,
269
- :my => MyStruct.new([1,2]) )
270
-
271
- # Seamlessly wraps the pointer in a struct
272
- struct.my.kind_of? MyStruct # true
273
-
274
- # Seamlessly unwraps the struct and stores the pointer
275
- struct.my = MyStruct.new([-4,-3])
276
-
277
-
278
- === Automatic Memory Managment
279
-
280
- Ruby-FFI already provides automatic memory management when you create
281
- a FFI::MemoryPointer or FFI::Buffer instance. When those instances are
282
- garbage collected, their memory is automatically released so it can be
283
- used elsewhere.
284
-
285
- That feature is used by NiceFFI::Struct when you create a new instance
286
- by passing a Hash, Array, String, or another instance. In those cases,
287
- new memory is allocated for the struct instance, and automatically
288
- released when the struct instance is galbage collected.
289
-
290
- NiceFFI::Struct also provides an optional automatic memory management
291
- system for normal pointers. To use this system, define a "release"
292
- class method in your class. Then if you create a new struct instance
293
- with an FFI::Pointer, the release class method will automatically be
294
- called when the memory for a struct instance needs to be freed.
295
-
296
- (This also applies to attached functions with TypedPointer return
297
- values. The pointers returned from those functions are wrapped in the
298
- struct class, so if you have defined the release class method, they
299
- will be automatically memory managed.)
300
-
301
- The release class method must accept an FFI::Pointer and call an
302
- appropriate function to free the struct's memory. Here's an example
303
- from Ruby-SDL-FFI:
304
-
305
-
306
- class Surface < NiceFFI::Struct
307
-
308
- def self.release( pointer )
309
- SDL.FreeSurface( pointer )
310
- end
311
-
312
- # ...
313
-
314
- end
315
-
316
-
317
- Note: the release class method should not have any side effects
318
- besides freeing the struct's memory. Don't be clever!
319
-
320
- The memory management system keeps a reference count for each pointer
321
- address, so the release class method will only be called when all
322
- struct instances that are using that memory have been garbage
323
- collected. That means it's safe to have many instances sharing the
324
- same memory.
325
-
326
- If you want to create an instance that doesn't use the memory
327
- management system, you can disable the :autorelease option when
328
- creating the instance, like so:
329
-
330
-
331
- struct = MyStructClass.new( a_pointer, :autorelease => false )
332
-
333
-
334
- == NiceFFI::OpaqueStruct
335
-
336
- Some C libraries have structs with no publicly-visible layout.
337
- Instead, the internal details are hidden, and only modified by calling
338
- functions in the library.
339
-
340
- For example, the SDL_mixer library has this definition in its header
341
- file:
342
-
343
-
344
- typedef struct _Mix_Music Mix_Music;
345
-
346
-
347
- "_Mix_Music" is a struct that is defined within SDL_mixer, but its
348
- internals are different depending on what features SDL_mixer was
349
- compiled with. The struct members are not revealed in the header file,
350
- so they can't be accessed like a normal struct.
351
-
352
- NiceFFI provides a class for handling special cases like this,
353
- NiceFFI::OpaqueStruct. OpaqueStruct has no layout and no members, and
354
- cannot be created by passing in Hashes, Arrays, etc. It simply holds a
355
- pointer to the struct memory. As with NiceStruct (and FFI::Struct),
356
- instances of OpaqueStruct-based classes can be passed directly to
357
- functions expecting a pointer of the appropriate struct type.
358
-
359
- OpaqueStruct features the same optional memory management system as
360
- NiceStruct. Read the "Automatic Memory Management" section above for
361
- information about how to use this feature.