ffi 1.0.9-x86-mingw32 → 1.0.12.pre-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/Rakefile +16 -16
- data/ext/ffi_c/AbstractMemory.c +376 -14
- data/ext/ffi_c/AbstractMemory.h +8 -0
- data/ext/ffi_c/ArrayType.c +28 -0
- data/ext/ffi_c/Buffer.c +109 -25
- data/ext/ffi_c/Call.c +16 -5
- data/ext/ffi_c/ClosurePool.c +21 -8
- data/ext/ffi_c/DataConverter.c +29 -0
- data/ext/ffi_c/DynamicLibrary.c +71 -2
- data/ext/ffi_c/Function.c +122 -11
- data/ext/ffi_c/Function.h +6 -0
- data/ext/ffi_c/FunctionInfo.c +21 -1
- data/ext/ffi_c/LastError.c +24 -0
- data/ext/ffi_c/MappedType.c +22 -0
- data/ext/ffi_c/MemoryPointer.c +19 -1
- data/ext/ffi_c/MemoryPointer.h +6 -0
- data/ext/ffi_c/MethodHandle.c +26 -11
- data/ext/ffi_c/Platform.c +17 -3
- data/ext/ffi_c/Pointer.c +106 -0
- data/ext/ffi_c/Pointer.h +6 -0
- data/ext/ffi_c/Struct.c +10 -4
- data/ext/ffi_c/Struct.h +2 -1
- data/ext/ffi_c/StructByReference.c +8 -0
- data/ext/ffi_c/StructByValue.c +8 -0
- data/ext/ffi_c/StructLayout.c +8 -2
- data/ext/ffi_c/Thread.c +131 -1
- data/ext/ffi_c/Thread.h +6 -0
- data/ext/ffi_c/Type.c +111 -17
- data/ext/ffi_c/Types.c +9 -2
- data/ext/ffi_c/Types.h +4 -0
- data/ext/ffi_c/Variadic.c +13 -4
- data/ext/ffi_c/compat.h +8 -0
- data/ext/ffi_c/endian.h +10 -1
- data/ext/ffi_c/extconf.rb +51 -35
- data/ext/ffi_c/ffi.c +5 -0
- data/ext/ffi_c/libffi.darwin.mk +15 -15
- data/ext/ffi_c/libffi.gnu.mk +3 -3
- data/ext/ffi_c/libffi.mk +4 -4
- data/ext/ffi_c/libffi.vc.mk +26 -0
- data/ext/ffi_c/libffi.vc64.mk +26 -0
- data/ext/ffi_c/libffi/ChangeLog +541 -0
- data/ext/ffi_c/libffi/ChangeLog.libffi +13 -87
- data/ext/ffi_c/libffi/LICENSE +3 -3
- data/ext/ffi_c/libffi/Makefile.am +41 -32
- data/ext/ffi_c/libffi/Makefile.in +95 -66
- data/ext/ffi_c/libffi/Makefile.vc +141 -0
- data/ext/ffi_c/libffi/Makefile.vc64 +141 -0
- data/ext/ffi_c/libffi/README +40 -4
- data/ext/ffi_c/libffi/aclocal.m4 +729 -7854
- data/ext/ffi_c/libffi/build-ios.sh +67 -0
- data/ext/ffi_c/libffi/compile +11 -10
- data/ext/ffi_c/libffi/config.guess +4 -1
- data/ext/ffi_c/libffi/config.sub +6 -3
- data/ext/ffi_c/libffi/configure +6264 -6354
- data/ext/ffi_c/libffi/configure.ac +155 -63
- data/ext/ffi_c/libffi/depcomp +81 -35
- data/ext/ffi_c/libffi/doc/libffi.info +78 -18
- data/ext/ffi_c/libffi/doc/libffi.texi +64 -5
- data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
- data/ext/ffi_c/libffi/doc/version.texi +4 -4
- data/ext/ffi_c/libffi/fficonfig.h.in +18 -0
- data/ext/ffi_c/libffi/fficonfig.hw +57 -0
- data/ext/ffi_c/libffi/include/Makefile.in +21 -3
- data/ext/ffi_c/libffi/include/ffi.h.in +42 -14
- data/ext/ffi_c/libffi/include/ffi.h.vc +427 -0
- data/ext/ffi_c/libffi/include/ffi.h.vc64 +427 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +9 -5
- data/ext/ffi_c/libffi/install-sh +364 -167
- data/ext/ffi_c/libffi/ltmain.sh +2599 -1369
- data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +176 -0
- data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +195 -0
- data/ext/ffi_c/libffi/m4/ax_check_compiler_flags.m4 +76 -0
- data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +63 -0
- data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +70 -0
- data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +300 -0
- data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +215 -0
- data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +79 -0
- data/ext/ffi_c/libffi/m4/libtool.m4 +1239 -768
- data/ext/ffi_c/libffi/m4/ltoptions.m4 +7 -6
- data/ext/ffi_c/libffi/m4/ltversion.m4 +6 -6
- data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +9 -3
- data/ext/ffi_c/libffi/man/Makefile.in +21 -3
- data/ext/ffi_c/libffi/mdate-sh +0 -0
- data/ext/ffi_c/libffi/missing +60 -44
- data/ext/ffi_c/libffi/msvcc.sh +197 -0
- data/ext/ffi_c/libffi/src/alpha/osf.S +39 -18
- data/ext/ffi_c/libffi/src/arm/ffi.c +443 -24
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +17 -1
- data/ext/ffi_c/libffi/src/arm/gentramp.sh +118 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +206 -15
- data/ext/ffi_c/libffi/src/arm/trampoline.S +4450 -0
- data/ext/ffi_c/libffi/src/avr32/ffi.c +4 -2
- data/ext/ffi_c/libffi/src/avr32/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/closures.c +17 -35
- data/ext/ffi_c/libffi/src/cris/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/cris/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/dlmalloc.c +66 -4
- data/ext/ffi_c/libffi/src/frv/ffitarget.h +2 -6
- data/ext/ffi_c/libffi/src/ia64/ffi.c +7 -5
- data/ext/ffi_c/libffi/src/ia64/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/java_raw_api.c +1 -1
- data/ext/ffi_c/libffi/src/m32r/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/m68k/ffi.c +10 -0
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/m68k/sysv.S +36 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +12 -5
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +18 -11
- data/ext/ffi_c/libffi/src/mips/n32.S +4 -4
- data/ext/ffi_c/libffi/src/moxie/eabi.S +128 -0
- data/ext/ffi_c/libffi/src/moxie/ffi.c +276 -0
- data/ext/ffi_c/libffi/src/pa/ffi.c +7 -4
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +6 -5
- data/ext/ffi_c/libffi/src/powerpc/aix.S +5 -1
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +2 -0
- data/ext/ffi_c/libffi/src/powerpc/asm.h +1 -1
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +215 -77
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +358 -100
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +11 -5
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +603 -172
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +17 -4
- data/ext/ffi_c/libffi/src/prep_cif.c +16 -13
- data/ext/ffi_c/libffi/src/s390/ffitarget.h +4 -2
- data/ext/ffi_c/libffi/src/sh/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/sparc/ffi.c +55 -11
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +5 -3
- data/ext/ffi_c/libffi/src/x86/ffi.c +54 -92
- data/ext/ffi_c/libffi/src/x86/ffi64.c +17 -8
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +15 -14
- data/ext/ffi_c/libffi/src/x86/sysv.S +40 -26
- data/ext/ffi_c/libffi/src/x86/unix64.S +4 -0
- data/ext/ffi_c/libffi/src/x86/win32.S +379 -191
- data/ext/ffi_c/libffi/src/x86/win64.S +15 -7
- data/ext/ffi_c/libffi/testsuite/Makefile.am +1 -1
- data/ext/ffi_c/libffi/testsuite/Makefile.in +22 -4
- data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +350 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +1 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +3 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +3 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +2 -3
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +2 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +17 -17
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +1 -3
- data/ext/ffi_c/win32/stdint.h +199 -0
- data/gen/Rakefile +18 -2
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/ffi.rb +13 -9
- data/lib/ffi/autopointer.rb +88 -26
- data/lib/ffi/enum.rb +42 -0
- data/lib/ffi/errno.rb +6 -1
- data/lib/ffi/ffi.rb +1 -0
- data/lib/ffi/io.rb +13 -2
- data/lib/ffi/library.rb +219 -24
- data/lib/ffi/memorypointer.rb +1 -33
- data/lib/ffi/platform.rb +21 -7
- data/lib/ffi/platform/arm-linux/types.conf +102 -0
- data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
- data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
- data/lib/ffi/platform/i486-gnu/types.conf +107 -0
- data/lib/ffi/platform/ia64-linux/types.conf +102 -0
- data/lib/ffi/platform/mips-linux/types.conf +102 -0
- data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
- data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
- data/lib/ffi/platform/s390-linux/types.conf +102 -0
- data/lib/ffi/platform/s390x-linux/types.conf +102 -0
- data/lib/ffi/platform/sparc-linux/types.conf +102 -0
- data/lib/ffi/platform/x86_64-freebsd/types.conf +126 -0
- data/lib/ffi/platform/x86_64-netbsd/types.conf +126 -0
- data/lib/ffi/pointer.rb +44 -0
- data/lib/ffi/struct.rb +2 -6
- data/lib/ffi/struct_layout_builder.rb +2 -1
- data/lib/ffi/tools/const_generator.rb +78 -26
- data/lib/ffi/tools/types_generator.rb +8 -1
- data/lib/ffi/types.rb +21 -1
- data/spec/ffi/async_callback_spec.rb +2 -2
- data/spec/ffi/bool_spec.rb +6 -6
- data/spec/ffi/buffer_spec.rb +23 -23
- data/spec/ffi/callback_spec.rb +101 -102
- data/spec/ffi/custom_type_spec.rb +20 -24
- data/spec/ffi/dup_spec.rb +7 -7
- data/spec/ffi/enum_spec.rb +127 -127
- data/spec/ffi/errno_spec.rb +2 -2
- data/spec/ffi/ffi_spec.rb +3 -3
- data/spec/ffi/function_spec.rb +10 -10
- data/spec/ffi/library_spec.rb +30 -12
- data/spec/ffi/managed_struct_spec.rb +4 -4
- data/spec/ffi/number_spec.rb +40 -40
- data/spec/ffi/pointer_spec.rb +21 -24
- data/spec/ffi/rbx/memory_pointer_spec.rb +17 -15
- data/spec/ffi/rbx/struct_spec.rb +2 -2
- data/spec/ffi/spec_helper.rb +1 -1
- data/spec/ffi/string_spec.rb +9 -9
- data/spec/ffi/strptr_spec.rb +3 -3
- data/spec/ffi/struct_callback_spec.rb +7 -7
- data/spec/ffi/struct_initialize_spec.rb +2 -2
- data/spec/ffi/struct_packed_spec.rb +6 -6
- data/spec/ffi/struct_spec.rb +94 -84
- data/spec/ffi/typedef_spec.rb +15 -4
- data/spec/ffi/union_spec.rb +3 -3
- data/spec/ffi/variadic_spec.rb +17 -14
- data/tasks/extension.rake +0 -1
- data/tasks/gem.rake +0 -1
- data/tasks/rdoc.rake +1 -1
- data/tasks/yard.rake +11 -0
- metadata +50 -11
- data/lib/1.9/ffi_c.so +0 -0
data/gen/Rakefile
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
1
2
|
require 'fileutils'
|
2
|
-
require
|
3
|
-
|
3
|
+
require 'ffi'
|
4
|
+
require 'ffi/platform'
|
5
|
+
require 'ffi/tools/types_generator'
|
6
|
+
types_conf = File.expand_path(File.join(FFI::Platform::CONF_DIR, 'types.conf'))
|
7
|
+
|
8
|
+
logfile = File.join(File.dirname(__FILE__), 'log')
|
4
9
|
|
5
10
|
file types_conf do |task|
|
6
11
|
options = {}
|
@@ -8,7 +13,18 @@ file types_conf do |task|
|
|
8
13
|
File.open(task.name, File::CREAT|File::TRUNC|File::RDWR, 0644) do |f|
|
9
14
|
f.puts FFI::TypesGenerator.generate(options)
|
10
15
|
end
|
16
|
+
File.open(logfile, 'w') do |log|
|
17
|
+
log.puts(types_conf)
|
18
|
+
end
|
11
19
|
end
|
12
20
|
|
13
21
|
task :default => types_conf do
|
14
22
|
end
|
23
|
+
|
24
|
+
task :clean do
|
25
|
+
File.readlines(logfile).each do |file|
|
26
|
+
file.strip!
|
27
|
+
rm_f file
|
28
|
+
end
|
29
|
+
rm_f logfile
|
30
|
+
end
|
data/lib/1.8/ffi_c.so
CHANGED
Binary file
|
data/lib/ffi.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
|
2
|
+
begin
|
3
|
+
if RUBY_VERSION =~ /1.8/
|
4
|
+
require '1.8/ffi_c'
|
5
|
+
elsif RUBY_VERSION =~ /1.9/
|
6
|
+
require '1.9/ffi_c'
|
7
|
+
else
|
8
|
+
require 'ffi_c'
|
9
|
+
end
|
10
|
+
rescue Exception
|
11
|
+
require 'ffi_c'
|
6
12
|
end
|
7
|
-
rescue Exception
|
8
|
-
require 'ffi_c'
|
9
|
-
end
|
10
13
|
|
11
|
-
require 'ffi/ffi'
|
14
|
+
require 'ffi/ffi'
|
15
|
+
end
|
data/lib/ffi/autopointer.rb
CHANGED
@@ -23,17 +23,31 @@ module FFI
|
|
23
23
|
class AutoPointer < Pointer
|
24
24
|
extend DataConverter
|
25
25
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
26
|
+
# @overload initialize(pointer, method)
|
27
|
+
# @param [Pointer] pointer
|
28
|
+
# @param [Method] method
|
29
|
+
# @return [self]
|
30
|
+
# The passed Method will be invoked at GC time.
|
31
|
+
# @overload initialize(pointer, proc)
|
32
|
+
# @param [Pointer] pointer
|
33
|
+
# @return [self]
|
34
|
+
# The passed Proc will be invoked at GC time (SEE WARNING BELOW!)
|
35
|
+
# @note WARNING: passing a proc _may_ cause your pointer to never be GC'd, unless you're
|
36
|
+
# careful to avoid trapping a reference to the pointer in the proc. See the test
|
37
|
+
# specs for examples.
|
38
|
+
# @overload initialize(pointer) { |p| ... }
|
39
|
+
# @param [Pointer] pointer
|
40
|
+
# @yieldparam [Pointer] p +pointer+ passed to the block
|
41
|
+
# @return [self]
|
42
|
+
# The passed block will be invoked at GC time.
|
43
|
+
# @note WARNING: passing a block will cause your pointer to never be GC'd. This is bad.
|
44
|
+
# @overload initialize(pointer)
|
45
|
+
# @param [Pointer] pointer
|
46
|
+
# @return [self]
|
47
|
+
# The pointer's release() class method will be invoked at GC time.
|
31
48
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# Please note that the safest, and therefore preferred, calling
|
36
|
-
# idiom is to pass a Method as the second parameter. Example usage:
|
49
|
+
# @note The safest, and therefore preferred, calling
|
50
|
+
# idiom is to pass a Method as the second parameter. Example usage:
|
37
51
|
#
|
38
52
|
# class PointerHelper
|
39
53
|
# def self.release(pointer)
|
@@ -43,12 +57,12 @@ module FFI
|
|
43
57
|
#
|
44
58
|
# p = AutoPointer.new(other_pointer, PointerHelper.method(:release))
|
45
59
|
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# The last calling idiom (only one parameter) is generally only
|
49
|
-
# going to be useful if you subclass AutoPointer, and override
|
50
|
-
# release(), which by default does nothing.
|
60
|
+
# The above code will cause PointerHelper#release to be invoked at GC time.
|
51
61
|
#
|
62
|
+
# @note
|
63
|
+
# The last calling idiom (only one parameter) is generally only
|
64
|
+
# going to be useful if you subclass {AutoPointer}, and override
|
65
|
+
# #release, which by default does nothing.
|
52
66
|
def initialize(ptr, proc=nil, &block)
|
53
67
|
super(ptr)
|
54
68
|
raise TypeError, "Invalid pointer" if ptr.nil? || !ptr.kind_of?(Pointer) \
|
@@ -67,52 +81,100 @@ module FFI
|
|
67
81
|
self
|
68
82
|
end
|
69
83
|
|
84
|
+
# @return [nil]
|
85
|
+
# Free the pointer.
|
70
86
|
def free
|
71
87
|
@releaser.free
|
72
88
|
end
|
73
89
|
|
90
|
+
# @param [Boolean] autorelease
|
91
|
+
# @return [Boolean] +autorelease+
|
92
|
+
# Set +autorelease+ property. See {Pointer Autorelease section at Pointer}.
|
74
93
|
def autorelease=(autorelease)
|
75
94
|
@releaser.autorelease=(autorelease)
|
76
95
|
end
|
77
96
|
|
97
|
+
# @abstract Base class for {AutoPointer}'s releasers.
|
98
|
+
#
|
99
|
+
# All subclasses of Releaser should define a +#release(ptr)+ method.
|
100
|
+
# A releaser is an object in charge of release an {AutoPointer}.
|
78
101
|
class Releaser
|
102
|
+
# @param [Pointer] ptr
|
103
|
+
# @param [#call] proc
|
104
|
+
# @return [nil]
|
105
|
+
# A new instance of Releaser.
|
79
106
|
def initialize(ptr, proc)
|
80
107
|
@ptr = ptr
|
81
108
|
@proc = proc
|
82
109
|
@autorelease = true
|
83
110
|
end
|
84
111
|
|
112
|
+
# @return [nil]
|
113
|
+
# Free pointer.
|
85
114
|
def free
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
115
|
+
if @ptr
|
116
|
+
release(@ptr)
|
117
|
+
@autorelease = false
|
118
|
+
@ptr = nil
|
119
|
+
@proc = nil
|
120
|
+
end
|
90
121
|
end
|
91
122
|
|
123
|
+
# @param [Boolean] autorelease
|
124
|
+
# @return [Boolean] autorelease
|
125
|
+
# Set +autorelease+ attribute for pointer managed by Releaser.
|
92
126
|
def autorelease=(autorelease)
|
93
|
-
|
94
|
-
@autorelease = autorelease
|
127
|
+
@autorelease = autorelease if @ptr
|
95
128
|
end
|
96
|
-
|
129
|
+
|
130
|
+
# @param args
|
131
|
+
# Release pointer if +autorelease+ is set.
|
132
|
+
def call(*args)
|
133
|
+
release(@ptr) if @autorelease && @ptr
|
134
|
+
end
|
135
|
+
|
97
136
|
end
|
98
137
|
|
138
|
+
# DefaultReleaser is a {Releaser} used when an {AutoPointer} is defined without Proc
|
139
|
+
# or Method. In this case, the pointer to release must be of a class derived from
|
140
|
+
# AutoPointer with a +#release+ class method.
|
99
141
|
class DefaultReleaser < Releaser
|
100
|
-
|
101
|
-
|
142
|
+
# @param [Pointer] ptr
|
143
|
+
# @return [nil]
|
144
|
+
# Release +ptr+ by using his #release class method.
|
145
|
+
def release(ptr)
|
146
|
+
@proc.release(ptr)
|
102
147
|
end
|
103
148
|
end
|
104
149
|
|
150
|
+
# CallableReleaser is a {Releaser} used when an {AutoPointer} is defined with a
|
151
|
+
# Proc or a Method.
|
105
152
|
class CallableReleaser < Releaser
|
106
|
-
|
107
|
-
|
153
|
+
# @param [Pointer] ptr
|
154
|
+
# @return [nil]
|
155
|
+
# Release +ptr+ by using Proc or Method defined at +ptr+ {AutoPointer#initialize initialization}.
|
156
|
+
def release(ptr)
|
157
|
+
@proc.call(ptr)
|
108
158
|
end
|
109
159
|
end
|
110
160
|
|
161
|
+
# Return native type of AutoPointer.
|
162
|
+
#
|
163
|
+
# Override {DataConverter#native_type}.
|
164
|
+
# @return [Type::POINTER]
|
165
|
+
# @raise {RuntimeError} if class does not implement a +#release+ method
|
111
166
|
def self.native_type
|
112
167
|
raise RuntimeError.new("no release method defined for #{self.inspect}") unless self.respond_to?(:release)
|
113
168
|
Type::POINTER
|
114
169
|
end
|
115
170
|
|
171
|
+
# Create a new AutoPointer.
|
172
|
+
#
|
173
|
+
# Override {DataConverter#from_native}.
|
174
|
+
# @overload self.from_native(ptr, ctx)
|
175
|
+
# @param [Pointer] ptr
|
176
|
+
# @param ctx not used. Please set +nil+.
|
177
|
+
# @return [AutoPointer]
|
116
178
|
def self.from_native(val, ctx)
|
117
179
|
self.new(val)
|
118
180
|
end
|
data/lib/ffi/enum.rb
CHANGED
@@ -21,20 +21,27 @@
|
|
21
21
|
|
22
22
|
module FFI
|
23
23
|
|
24
|
+
# An instance of this class permits to manage {Enum}s. In fact, Enums is a collection of {Enum}s.
|
24
25
|
class Enums
|
25
26
|
|
27
|
+
# @return [nil]
|
26
28
|
def initialize
|
27
29
|
@all_enums = Array.new
|
28
30
|
@tagged_enums = Hash.new
|
29
31
|
@symbol_map = Hash.new
|
30
32
|
end
|
31
33
|
|
34
|
+
# @param [Enum] enum
|
35
|
+
# Add an {Enum} to the collection.
|
32
36
|
def <<(enum)
|
33
37
|
@all_enums << enum
|
34
38
|
@tagged_enums[enum.tag] = enum unless enum.tag.nil?
|
35
39
|
@symbol_map.merge!(enum.symbol_map)
|
36
40
|
end
|
37
41
|
|
42
|
+
# @param query enum tag or part of an enum name
|
43
|
+
# @return [Enum]
|
44
|
+
# Find a {Enum} in collection.
|
38
45
|
def find(query)
|
39
46
|
if @tagged_enums.has_key?(query)
|
40
47
|
@tagged_enums[query]
|
@@ -43,17 +50,33 @@ module FFI
|
|
43
50
|
end
|
44
51
|
end
|
45
52
|
|
53
|
+
# @param symbol a symbol to find in merge symbol maps of all enums.
|
54
|
+
# @return a symbol
|
46
55
|
def __map_symbol(symbol)
|
47
56
|
@symbol_map[symbol]
|
48
57
|
end
|
49
58
|
|
50
59
|
end
|
51
60
|
|
61
|
+
# Represents a C enum.
|
62
|
+
#
|
63
|
+
# For a C enum:
|
64
|
+
# enum fruits {
|
65
|
+
# apple,
|
66
|
+
# banana,
|
67
|
+
# orange,
|
68
|
+
# pineapple
|
69
|
+
# };
|
70
|
+
# are defined this vocabulary:
|
71
|
+
# * a _symbol_ is a word from the enumeration (ie. _apple_, by example);
|
72
|
+
# * a _value_ is the value of a symbol in the enumeration (by example, apple has value _0_ and banana _1_).
|
52
73
|
class Enum
|
53
74
|
include DataConverter
|
54
75
|
|
55
76
|
attr_reader :tag
|
56
77
|
|
78
|
+
# @param [nil, Enumerable] info
|
79
|
+
# @param tag enum tag
|
57
80
|
def initialize(info, tag=nil)
|
58
81
|
@tag = tag
|
59
82
|
@kv_map = Hash.new
|
@@ -75,10 +98,20 @@ module FFI
|
|
75
98
|
@vk_map = Hash[@kv_map.map{|k,v| [v,k]}]
|
76
99
|
end
|
77
100
|
|
101
|
+
# @return [Array] enum symbol names
|
78
102
|
def symbols
|
79
103
|
@kv_map.keys
|
80
104
|
end
|
81
105
|
|
106
|
+
# Get a symbol or a value from the enum.
|
107
|
+
# @overload [](query)
|
108
|
+
# Get enum value from symbol.
|
109
|
+
# @param [Symbol] query
|
110
|
+
# @return [Integer]
|
111
|
+
# @overload [](query)
|
112
|
+
# Get enum symbol from value.
|
113
|
+
# @param [Integer] query
|
114
|
+
# @return [Symbol]
|
82
115
|
def [](query)
|
83
116
|
case query
|
84
117
|
when Symbol
|
@@ -89,6 +122,8 @@ module FFI
|
|
89
122
|
end
|
90
123
|
alias find []
|
91
124
|
|
125
|
+
# Get the symbol map.
|
126
|
+
# @return [Hash]
|
92
127
|
def symbol_map
|
93
128
|
@kv_map
|
94
129
|
end
|
@@ -96,10 +131,15 @@ module FFI
|
|
96
131
|
alias to_h symbol_map
|
97
132
|
alias to_hash symbol_map
|
98
133
|
|
134
|
+
# Get native type of Enum
|
135
|
+
# @return [Type::INT]
|
99
136
|
def native_type
|
100
137
|
Type::INT
|
101
138
|
end
|
102
139
|
|
140
|
+
# @param [Symbol, Integer, #to_int] val
|
141
|
+
# @param ctx unused
|
142
|
+
# @return [Integer] value of a enum symbol
|
103
143
|
def to_native(val, ctx)
|
104
144
|
@kv_map[val] || if val.is_a?(Integer)
|
105
145
|
val
|
@@ -110,6 +150,8 @@ module FFI
|
|
110
150
|
end
|
111
151
|
end
|
112
152
|
|
153
|
+
# @param val
|
154
|
+
# @return symbol name if it exists for +val+.
|
113
155
|
def from_native(val, ctx)
|
114
156
|
@vk_map[val] || val
|
115
157
|
end
|
data/lib/ffi/errno.rb
CHANGED
@@ -19,10 +19,15 @@
|
|
19
19
|
#
|
20
20
|
|
21
21
|
module FFI
|
22
|
+
# @return (see FFI::LastError.error)
|
23
|
+
# @see FFI::LastError.error
|
22
24
|
def self.errno
|
23
25
|
FFI::LastError.error
|
24
26
|
end
|
27
|
+
# @param error (see FFI::LastError.error=)
|
28
|
+
# @return (see FFI::LastError.error=)
|
29
|
+
# @see FFI::LastError.error=
|
25
30
|
def self.errno=(error)
|
26
31
|
FFI::LastError.error = error
|
27
32
|
end
|
28
|
-
end
|
33
|
+
end
|
data/lib/ffi/ffi.rb
CHANGED
data/lib/ffi/io.rb
CHANGED
@@ -19,15 +19,26 @@
|
|
19
19
|
#
|
20
20
|
|
21
21
|
module FFI
|
22
|
+
|
23
|
+
# This module implements a couple of class methods to play with IO.
|
22
24
|
module IO
|
25
|
+
# @param [Integer] fd file decriptor
|
26
|
+
# @param [String] mode mode string
|
27
|
+
# @return [::IO]
|
28
|
+
# Synonym for IO::for_fd.
|
23
29
|
def self.for_fd(fd, mode = "r")
|
24
30
|
::IO.for_fd(fd, mode)
|
25
31
|
end
|
26
32
|
|
33
|
+
# @param [#read] io io to read from
|
34
|
+
# @param [AbstractMemory] buf destination for data read from +io+
|
35
|
+
# @param [nil, Numeric] len maximul number of bytes to read from +io+. If +nil+,
|
36
|
+
# read until end of file.
|
37
|
+
# @return [Numeric] length really read, in bytes
|
27
38
|
#
|
28
|
-
# A version of IO#read that reads into a native buffer
|
39
|
+
# A version of IO#read that reads data from an IO and put then into a native buffer.
|
29
40
|
#
|
30
|
-
# This will be optimized at some future time to eliminate the double copy
|
41
|
+
# This will be optimized at some future time to eliminate the double copy.
|
31
42
|
#
|
32
43
|
def self.native_read(io, buf, len)
|
33
44
|
tmp = io.read(len)
|
data/lib/ffi/library.rb
CHANGED
@@ -21,6 +21,16 @@
|
|
21
21
|
module FFI
|
22
22
|
CURRENT_PROCESS = USE_THIS_PROCESS_AS_LIBRARY = Object.new
|
23
23
|
|
24
|
+
# @param [#to_s] lib library name
|
25
|
+
# @return [String] library name formatted for current platform
|
26
|
+
# Transform a generic library name to a platform library name
|
27
|
+
# @example
|
28
|
+
# # Linux
|
29
|
+
# FFI.map_library_name 'c' # -> "libc.so.6"
|
30
|
+
# FFI.map_library_name 'jpeg' # -> "libjpeg.so"
|
31
|
+
# # Windows
|
32
|
+
# FFI.map_library_name 'c' # -> "msvcrt.dll"
|
33
|
+
# FFI.map_library_name 'jpeg' # -> "jpeg.dll"
|
24
34
|
def self.map_library_name(lib)
|
25
35
|
# Mangle the library name to reflect the native library naming conventions
|
26
36
|
lib = lib.to_s unless lib.kind_of?(String)
|
@@ -28,27 +38,51 @@ module FFI
|
|
28
38
|
|
29
39
|
if lib && File.basename(lib) == lib
|
30
40
|
lib = Platform::LIBPREFIX + lib unless lib =~ /^#{Platform::LIBPREFIX}/
|
31
|
-
r = Platform::
|
41
|
+
r = Platform::IS_GNU ? "\\.so($|\\.[1234567890]+)" : "\\.#{Platform::LIBSUFFIX}$"
|
32
42
|
lib += ".#{Platform::LIBSUFFIX}" unless lib =~ /#{r}/
|
33
43
|
end
|
34
44
|
|
35
45
|
lib
|
36
46
|
end
|
37
47
|
|
48
|
+
# Exception raised when a function is not found in libraries
|
38
49
|
class NotFoundError < LoadError
|
39
50
|
def initialize(function, *libraries)
|
40
51
|
super("Function '#{function}' not found in [#{libraries[0].nil? ? 'current process' : libraries.join(", ")}]")
|
41
52
|
end
|
42
53
|
end
|
43
54
|
|
55
|
+
# This module is the base to use native functions.
|
56
|
+
#
|
57
|
+
# A basic usage may be:
|
58
|
+
# require 'ffi'
|
59
|
+
#
|
60
|
+
# module Hello
|
61
|
+
# extend FFI::Library
|
62
|
+
# ffi_lib FFI::Library::LIBC
|
63
|
+
# attach_function 'puts', [ :string ], :int
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# Hello.puts("Hello, World")
|
67
|
+
#
|
68
|
+
#
|
44
69
|
module Library
|
45
70
|
CURRENT_PROCESS = FFI::CURRENT_PROCESS
|
46
71
|
LIBC = FFI::Platform::LIBC
|
47
72
|
|
73
|
+
# @param mod extended object
|
74
|
+
# @return [nil]
|
75
|
+
# @raise {RuntimeError} if +mod+ is not a Module
|
76
|
+
# Test if extended object is a Module. If not, raise RuntimeError.
|
48
77
|
def self.extended(mod)
|
49
78
|
raise RuntimeError.new("must only be extended by module") unless mod.kind_of?(Module)
|
50
79
|
end
|
51
80
|
|
81
|
+
|
82
|
+
# @param [Array] names names of libraries to load
|
83
|
+
# @return [Array<DynamicLibrary>]
|
84
|
+
# @raise {LoadError} if a library cannot be opened
|
85
|
+
# Load native libraries.
|
52
86
|
def ffi_lib(*names)
|
53
87
|
lib_flags = defined?(@ffi_lib_flags) ? @ffi_lib_flags : FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_LOCAL
|
54
88
|
ffi_libs = names.map do |name|
|
@@ -67,12 +101,24 @@ module FFI
|
|
67
101
|
break if lib
|
68
102
|
|
69
103
|
rescue Exception => ex
|
70
|
-
|
104
|
+
ldscript = false
|
105
|
+
if ex.message =~ /(([^ \t()])+\.so([^ \t:()])*):([ \t])*invalid ELF header/
|
106
|
+
if File.read($1) =~ /GROUP *\( *([^ \)]+) *\)/
|
107
|
+
libname = $1
|
108
|
+
ldscript = true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
if ldscript
|
113
|
+
retry
|
114
|
+
else
|
115
|
+
errors[libname] = ex
|
116
|
+
end
|
71
117
|
end
|
72
118
|
end
|
73
119
|
|
74
120
|
if lib.nil?
|
75
|
-
raise LoadError.new(errors.values.join(
|
121
|
+
raise LoadError.new(errors.values.join(".\n"))
|
76
122
|
end
|
77
123
|
|
78
124
|
# return the found lib
|
@@ -83,17 +129,32 @@ module FFI
|
|
83
129
|
@ffi_libs = ffi_libs
|
84
130
|
end
|
85
131
|
|
86
|
-
|
87
|
-
|
88
|
-
|
132
|
+
# Set the calling convention for {#attach_function} and {#callback}
|
133
|
+
#
|
134
|
+
# @see http://en.wikipedia.org/wiki/Stdcall#stdcall
|
135
|
+
# @note +:stdcall+ is typically used for attaching Windows API functions
|
136
|
+
#
|
137
|
+
# @param [Symbol] convention one of +:default+, +:stdcall+
|
138
|
+
# @return [Symbol] the new calling convention
|
139
|
+
def ffi_convention(convention = nil)
|
140
|
+
@ffi_convention ||= :default
|
141
|
+
@ffi_convention = convention if convention
|
142
|
+
@ffi_convention
|
89
143
|
end
|
90
144
|
|
91
|
-
|
145
|
+
# @see #ffi_lib
|
146
|
+
# @return [Array<FFI::DynamicLibrary>] array of currently loaded FFI libraries
|
147
|
+
# @raise [LoadError] if no libraries have been loaded (using {#ffi_lib})
|
148
|
+
# Get FFI libraries loaded using {#ffi_lib}.
|
92
149
|
def ffi_libraries
|
93
150
|
raise LoadError.new("no library specified") if !defined?(@ffi_libs) || @ffi_libs.empty?
|
94
151
|
@ffi_libs
|
95
152
|
end
|
96
153
|
|
154
|
+
# Flags used in {#ffi_lib}.
|
155
|
+
#
|
156
|
+
# This map allows you to supply symbols to {#ffi_lib_flags} instead of
|
157
|
+
# the actual constants.
|
97
158
|
FlagsMap = {
|
98
159
|
:global => DynamicLibrary::RTLD_GLOBAL,
|
99
160
|
:local => DynamicLibrary::RTLD_LOCAL,
|
@@ -101,26 +162,64 @@ module FFI
|
|
101
162
|
:now => DynamicLibrary::RTLD_NOW
|
102
163
|
}
|
103
164
|
|
165
|
+
# Sets library flags for {#ffi_lib}.
|
166
|
+
#
|
167
|
+
# @example
|
168
|
+
# ffi_lib_flags(:lazy, :local) # => 5
|
169
|
+
#
|
170
|
+
# @param [Symbol, …] flags (see {FlagsMap})
|
171
|
+
# @return [Fixnum] the new value
|
104
172
|
def ffi_lib_flags(*flags)
|
105
173
|
@ffi_lib_flags = flags.inject(0) { |result, f| result | FlagsMap[f] }
|
106
174
|
end
|
107
175
|
|
108
|
-
|
176
|
+
|
109
177
|
##
|
110
|
-
#
|
178
|
+
# @overload attach_function(func, args, returns, options = {})
|
179
|
+
# @example attach function without an explicit name
|
180
|
+
# module Foo
|
181
|
+
# extend FFI::Library
|
182
|
+
# ffi_lib FFI::Library::LIBC
|
183
|
+
# attach_function :malloc, [:size_t], :pointer
|
184
|
+
# end
|
185
|
+
# # now callable via Foo.malloc
|
186
|
+
# @overload attach_function(name, func, args, returns, options = {})
|
187
|
+
# @example attach function with an explicit name
|
188
|
+
# module Bar
|
189
|
+
# extend FFI::Library
|
190
|
+
# ffi_lib FFI::Library::LIBC
|
191
|
+
# attach_function :c_malloc, :malloc, [:size_t], :pointer
|
192
|
+
# end
|
193
|
+
# # now callable via Bar.c_malloc
|
194
|
+
#
|
195
|
+
# Attach C function +func+ to this module.
|
196
|
+
#
|
111
197
|
#
|
112
|
-
|
198
|
+
# @param [#to_s] name name of ruby method to attach as
|
199
|
+
# @param [#to_s] func name of C function to attach
|
200
|
+
# @param [Array<Symbol>] args an array of types
|
201
|
+
# @param [Symbol] returns type of return value
|
202
|
+
# @option options [Boolean] :blocking (@blocking) set to true if the C function is a blocking call
|
203
|
+
# @option options [Symbol] :convention (:default) calling convention (see {#ffi_convention})
|
204
|
+
# @option options [FFI::Enums] :enums
|
205
|
+
# @option options [Hash] :type_map
|
206
|
+
#
|
207
|
+
# @return [FFI::VariadicInvoker]
|
208
|
+
#
|
209
|
+
# @raise [FFI::NotFoundError] if +func+ cannot be found in the attached libraries (see {#ffi_lib})
|
210
|
+
def attach_function(name, func, args, returns = nil, options = nil)
|
211
|
+
mname, a2, a3, a4, a5 = name, func, args, returns, options
|
113
212
|
cname, arg_types, ret_type, opts = (a4 && (a2.is_a?(String) || a2.is_a?(Symbol))) ? [ a2, a3, a4, a5 ] : [ mname.to_s, a2, a3, a4 ]
|
114
213
|
|
115
214
|
# Convert :foo to the native type
|
116
215
|
arg_types.map! { |e| find_type(e) }
|
117
216
|
options = {
|
118
|
-
:convention =>
|
217
|
+
:convention => ffi_convention,
|
119
218
|
:type_map => defined?(@ffi_typedefs) ? @ffi_typedefs : nil,
|
120
219
|
:blocking => defined?(@blocking) && @blocking,
|
121
220
|
:enums => defined?(@ffi_enums) ? @ffi_enums : nil,
|
122
221
|
}
|
123
|
-
|
222
|
+
|
124
223
|
@blocking = false
|
125
224
|
options.merge!(opts) if opts && opts.is_a?(Hash)
|
126
225
|
|
@@ -129,7 +228,10 @@ module FFI
|
|
129
228
|
ffi_libraries.each do |lib|
|
130
229
|
if invokers.empty?
|
131
230
|
begin
|
132
|
-
function =
|
231
|
+
function = nil
|
232
|
+
function_names(cname, arg_types).find do |fname|
|
233
|
+
function = lib.find_function(fname)
|
234
|
+
end
|
133
235
|
raise LoadError unless function
|
134
236
|
|
135
237
|
invokers << if arg_types.length > 0 && arg_types[arg_types.length - 1] == FFI::NativeType::VARARGS
|
@@ -139,7 +241,7 @@ module FFI
|
|
139
241
|
Function.new(find_type(ret_type), arg_types, function, options)
|
140
242
|
end
|
141
243
|
|
142
|
-
rescue LoadError
|
244
|
+
rescue LoadError
|
143
245
|
end
|
144
246
|
end
|
145
247
|
end
|
@@ -150,7 +252,56 @@ module FFI
|
|
150
252
|
invoker
|
151
253
|
end
|
152
254
|
|
255
|
+
# @param [#to_s] name function name
|
256
|
+
# @param [Array] arg_types function's argument types
|
257
|
+
# @return [Array<String>]
|
258
|
+
# This function returns a list of possible names to lookup.
|
259
|
+
# @note Function names on windows may be decorated if they are using stdcall. See
|
260
|
+
# * http://en.wikipedia.org/wiki/Name_mangling#C_name_decoration_in_Microsoft_Windows
|
261
|
+
# * http://msdn.microsoft.com/en-us/library/zxk0tw93%28v=VS.100%29.aspx
|
262
|
+
# * http://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions#STDCALL
|
263
|
+
# Note that decorated names can be overridden via def files. Also note that the
|
264
|
+
# windows api, although using, doesn't have decorated names.
|
265
|
+
def function_names(name, arg_types)
|
266
|
+
result = [name.to_s]
|
267
|
+
if ffi_convention == :stdcall
|
268
|
+
# Get the size of each parameter
|
269
|
+
size = arg_types.inject(0) do |mem, arg|
|
270
|
+
mem + arg.size
|
271
|
+
end
|
272
|
+
|
273
|
+
# Next, the size must be a multiple of 4
|
274
|
+
size += (4 - size) % 4
|
275
|
+
|
276
|
+
result << "_#{name.to_s}@#{size}" # win32
|
277
|
+
result << "#{name.to_s}@#{size}" # win64
|
278
|
+
end
|
279
|
+
result
|
280
|
+
end
|
153
281
|
|
282
|
+
# @overload attach_variable(mname, cname, type)
|
283
|
+
# @example
|
284
|
+
# module Bar
|
285
|
+
# extend FFI::Library
|
286
|
+
# ffi_lib 'my_lib'
|
287
|
+
# attach_variable :c_myvar, :myvar, :long
|
288
|
+
# end
|
289
|
+
# # now callable via Bar.c_myvar
|
290
|
+
# @overload attach_variable(cname, type)
|
291
|
+
# @example
|
292
|
+
# module Bar
|
293
|
+
# extend FFI::Library
|
294
|
+
# ffi_lib 'my_lib'
|
295
|
+
# attach_variable :myvar, :long
|
296
|
+
# end
|
297
|
+
# # now callable via Bar.myvar
|
298
|
+
# @param [#to_s] mname name of ruby method to attach as
|
299
|
+
# @param [#to_s] cname name of C variable to attach
|
300
|
+
# @param [DataConverter, Struct, Symbol, Type] type C varaible's type
|
301
|
+
# @return [DynamicLibrary::Symbol]
|
302
|
+
# @raise {FFI::NotFoundError} if +cname+ cannot be found in libraries
|
303
|
+
#
|
304
|
+
# Attach C variable +cname+ to this module.
|
154
305
|
def attach_variable(mname, a1, a2 = nil)
|
155
306
|
cname, type = a2 ? [ a1, a2 ] : [ mname.to_s, a1 ]
|
156
307
|
address = nil
|
@@ -171,7 +322,7 @@ module FFI
|
|
171
322
|
def self.#{mname}
|
172
323
|
@@ffi_gvar_#{mname}
|
173
324
|
end
|
174
|
-
|
325
|
+
code
|
175
326
|
|
176
327
|
else
|
177
328
|
sc = Class.new(FFI::Struct)
|
@@ -195,6 +346,13 @@ module FFI
|
|
195
346
|
address
|
196
347
|
end
|
197
348
|
|
349
|
+
|
350
|
+
# @overload callback(name, params, ret)
|
351
|
+
# @overload callback(params, ret)
|
352
|
+
# @param name callback name to add to type map
|
353
|
+
# @param [Array] params array of parameters' types
|
354
|
+
# @param [DataConverter, Struct, Symbol, Type] ret callback return type
|
355
|
+
# @return [FFI::CallbackInfo]
|
198
356
|
def callback(*args)
|
199
357
|
raise ArgumentError, "wrong number of arguments" if args.length < 2 || args.length > 3
|
200
358
|
name, params, ret = if args.length == 3
|
@@ -204,7 +362,7 @@ module FFI
|
|
204
362
|
end
|
205
363
|
|
206
364
|
options = Hash.new
|
207
|
-
options[:convention] =
|
365
|
+
options[:convention] = ffi_convention
|
208
366
|
options[:enums] = @ffi_enums if defined?(@ffi_enums)
|
209
367
|
cb = FFI::CallbackInfo.new(find_type(ret), params.map { |e| find_type(e) }, options)
|
210
368
|
|
@@ -216,6 +374,22 @@ module FFI
|
|
216
374
|
cb
|
217
375
|
end
|
218
376
|
|
377
|
+
# @param [DataConverter, Symbol, Type] old
|
378
|
+
# @param add
|
379
|
+
# @param [] info
|
380
|
+
# @return [FFI::Enum, FFI::Type]
|
381
|
+
# Register or get an already registered type definition.
|
382
|
+
#
|
383
|
+
# To register a new type definition, +old+ should be a {FFI::Type}. +add+
|
384
|
+
# is in this case the type definition.
|
385
|
+
#
|
386
|
+
# If +old+ is a {DataConverter}, a {Type::Mapped} is returned.
|
387
|
+
#
|
388
|
+
# If +old+ is +:enum+
|
389
|
+
# * and +add+ is an +Array+, a call to {#enum} is made with +add+ as single parameter;
|
390
|
+
# * in others cases, +info+ is used to create a named enum.
|
391
|
+
#
|
392
|
+
# If +old+ is a key for type map, #typedef get +old+ type definition.
|
219
393
|
def typedef(old, add, info=nil)
|
220
394
|
@ffi_typedefs = Hash.new unless defined?(@ffi_typedefs)
|
221
395
|
|
@@ -240,13 +414,25 @@ module FFI
|
|
240
414
|
end
|
241
415
|
end
|
242
416
|
|
417
|
+
# @overload enum(name, values)
|
418
|
+
# Create a named enum.
|
419
|
+
# @example
|
420
|
+
# enum :foo, [:zero, :one, :two] # named enum
|
421
|
+
# @param [Symbol] name name for new enum
|
422
|
+
# @param [Array] values values for enum
|
423
|
+
# @overload enum(*args)
|
424
|
+
# Create an unnamed enum.
|
425
|
+
# @example
|
426
|
+
# enum :zero, :one, :two # unnamed enum
|
427
|
+
# @param args values for enum
|
428
|
+
# @overload enum(values)
|
429
|
+
# Create an unnamed enum.
|
430
|
+
# @example
|
431
|
+
# enum [:zero, :one, :two] # unnamed enum, equivalent to above example
|
432
|
+
# @param [Array] values values for enum
|
433
|
+
# @return [FFI::Enum]
|
434
|
+
# Create a new {FFI::Enum}.
|
243
435
|
def enum(*args)
|
244
|
-
#
|
245
|
-
# enum can be called as:
|
246
|
-
# enum :zero, :one, :two # unnamed enum
|
247
|
-
# enum [ :zero, :one, :two ] # equivalent to above
|
248
|
-
# enum :foo, [ :zero, :one, :two ] create an enum named :foo
|
249
|
-
#
|
250
436
|
name, values = if args[0].kind_of?(Symbol) && args[1].kind_of?(Array)
|
251
437
|
[ args[0], args[1] ]
|
252
438
|
elsif args[0].kind_of?(Array)
|
@@ -262,18 +448,27 @@ module FFI
|
|
262
448
|
e
|
263
449
|
end
|
264
450
|
|
451
|
+
# @param name
|
452
|
+
# @return [FFI::Enum]
|
453
|
+
# Find an enum by name.
|
265
454
|
def enum_type(name)
|
266
455
|
@ffi_enums.find(name) if defined?(@ffi_enums)
|
267
456
|
end
|
268
457
|
|
458
|
+
# @param symbol
|
459
|
+
# @return [FFI::Enum]
|
460
|
+
# Find an enum by a symbol it contains.
|
269
461
|
def enum_value(symbol)
|
270
462
|
@ffi_enums.__map_symbol(symbol)
|
271
463
|
end
|
272
464
|
|
465
|
+
# @param [DataConverter, Type, Struct, Symbol] t type to find
|
466
|
+
# @return [Type]
|
467
|
+
# Find a type definition.
|
273
468
|
def find_type(t)
|
274
469
|
if t.kind_of?(Type)
|
275
470
|
t
|
276
|
-
|
471
|
+
|
277
472
|
elsif defined?(@ffi_typedefs) && @ffi_typedefs.has_key?(t)
|
278
473
|
@ffi_typedefs[t]
|
279
474
|
|
@@ -283,7 +478,7 @@ module FFI
|
|
283
478
|
elsif t.is_a?(DataConverter)
|
284
479
|
# Add a typedef so next time the converter is used, it hits the cache
|
285
480
|
typedef Type::Mapped.new(t), t
|
286
|
-
|
481
|
+
|
287
482
|
end || FFI.find_type(t)
|
288
483
|
end
|
289
484
|
end
|