ffi 0.4.0-x86-mswin32
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/LICENSE +51 -0
- data/README.rdoc +69 -0
- data/Rakefile +142 -0
- data/ext/ffi_c/AbstractMemory.c +412 -0
- data/ext/ffi_c/AbstractMemory.h +68 -0
- data/ext/ffi_c/AutoPointer.c +60 -0
- data/ext/ffi_c/AutoPointer.h +18 -0
- data/ext/ffi_c/Buffer.c +171 -0
- data/ext/ffi_c/Callback.c +374 -0
- data/ext/ffi_c/Callback.h +47 -0
- data/ext/ffi_c/DynamicLibrary.c +213 -0
- data/ext/ffi_c/DynamicLibrary.h +22 -0
- data/ext/ffi_c/Invoker.c +962 -0
- data/ext/ffi_c/LastError.c +135 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +156 -0
- data/ext/ffi_c/MemoryPointer.h +20 -0
- data/ext/ffi_c/NullPointer.c +143 -0
- data/ext/ffi_c/Platform.c +59 -0
- data/ext/ffi_c/Platform.h +16 -0
- data/ext/ffi_c/Pointer.c +164 -0
- data/ext/ffi_c/Pointer.h +25 -0
- data/ext/ffi_c/Struct.c +477 -0
- data/ext/ffi_c/Struct.h +26 -0
- data/ext/ffi_c/Type.c +230 -0
- data/ext/ffi_c/Type.h +28 -0
- data/ext/ffi_c/Types.c +118 -0
- data/ext/ffi_c/Types.h +54 -0
- data/ext/ffi_c/compat.h +22 -0
- data/ext/ffi_c/endian.h +40 -0
- data/ext/ffi_c/extconf.rb +31 -0
- data/ext/ffi_c/ffi.c +76 -0
- data/ext/ffi_c/libffi.bsd.mk +34 -0
- data/ext/ffi_c/libffi.darwin.mk +75 -0
- data/ext/ffi_c/libffi.gnu.mk +29 -0
- data/ext/ffi_c/libffi.mk +13 -0
- data/ext/ffi_c/libffi/ChangeLog +3243 -0
- data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
- data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
- data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
- data/ext/ffi_c/libffi/LICENSE +21 -0
- data/ext/ffi_c/libffi/Makefile.am +177 -0
- data/ext/ffi_c/libffi/Makefile.in +1640 -0
- data/ext/ffi_c/libffi/README +328 -0
- data/ext/ffi_c/libffi/TODO +1 -0
- data/ext/ffi_c/libffi/acinclude.m4 +92 -0
- data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
- data/ext/ffi_c/libffi/compile +142 -0
- data/ext/ffi_c/libffi/config.guess +1516 -0
- data/ext/ffi_c/libffi/config.sub +1626 -0
- data/ext/ffi_c/libffi/configure +24414 -0
- data/ext/ffi_c/libffi/configure.ac +365 -0
- data/ext/ffi_c/libffi/configure.host +11 -0
- data/ext/ffi_c/libffi/depcomp +584 -0
- data/ext/ffi_c/libffi/doc/libffi.info +533 -0
- data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
- data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
- data/ext/ffi_c/libffi/doc/version.texi +4 -0
- data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
- data/ext/ffi_c/libffi/include/Makefile.am +9 -0
- data/ext/ffi_c/libffi/include/Makefile.in +422 -0
- data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
- data/ext/ffi_c/libffi/install-sh +323 -0
- data/ext/ffi_c/libffi/libffi.pc.in +10 -0
- data/ext/ffi_c/libffi/libtool-version +29 -0
- data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
- data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
- data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
- data/ext/ffi_c/libffi/ltconfig +2862 -0
- data/ext/ffi_c/libffi/ltmain.sh +6930 -0
- data/ext/ffi_c/libffi/man/Makefile.am +8 -0
- data/ext/ffi_c/libffi/man/Makefile.in +395 -0
- data/ext/ffi_c/libffi/man/ffi.3 +31 -0
- data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
- data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
- data/ext/ffi_c/libffi/mdate-sh +201 -0
- data/ext/ffi_c/libffi/missing +353 -0
- data/ext/ffi_c/libffi/mkinstalldirs +158 -0
- data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
- data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
- data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
- data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
- data/ext/ffi_c/libffi/src/closures.c +596 -0
- data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
- data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
- data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
- data/ext/ffi_c/libffi/src/debug.c +59 -0
- data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
- data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
- data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
- data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
- data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
- data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
- data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
- data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
- data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
- data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
- data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
- data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
- data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
- data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
- data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
- data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
- data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
- data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
- data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
- data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
- data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
- data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
- data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
- data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
- data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
- data/ext/ffi_c/libffi/src/raw_api.c +254 -0
- data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
- data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
- data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
- data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
- data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
- data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
- data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
- data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
- data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
- data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
- data/ext/ffi_c/libffi/src/types.c +77 -0
- data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
- data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
- data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
- data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
- data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
- data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
- data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
- data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
- data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
- data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
- data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
- data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
- data/ext/ffi_c/libffi/texinfo.tex +7482 -0
- data/ext/ffi_c/rbffi.h +23 -0
- data/gen/Rakefile +12 -0
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
- data/lib/ffi.rb +11 -0
- data/lib/ffi/autopointer.rb +61 -0
- data/lib/ffi/buffer.rb +0 -0
- data/lib/ffi/callback.rb +10 -0
- data/lib/ffi/enum.rb +78 -0
- data/lib/ffi/errno.rb +8 -0
- data/lib/ffi/ffi.rb +96 -0
- data/lib/ffi/io.rb +21 -0
- data/lib/ffi/library.rb +243 -0
- data/lib/ffi/managedstruct.rb +55 -0
- data/lib/ffi/memorypointer.rb +73 -0
- data/lib/ffi/platform.rb +78 -0
- data/lib/ffi/pointer.rb +119 -0
- data/lib/ffi/struct.rb +354 -0
- data/lib/ffi/tools/const_generator.rb +177 -0
- data/lib/ffi/tools/generator.rb +58 -0
- data/lib/ffi/tools/generator_task.rb +35 -0
- data/lib/ffi/tools/struct_generator.rb +194 -0
- data/lib/ffi/tools/types_generator.rb +123 -0
- data/lib/ffi/types.rb +153 -0
- data/lib/ffi/union.rb +17 -0
- data/lib/ffi/variadic.rb +30 -0
- data/spec/ffi/bool_spec.rb +24 -0
- data/spec/ffi/buffer_spec.rb +196 -0
- data/spec/ffi/callback_spec.rb +560 -0
- data/spec/ffi/enum_spec.rb +164 -0
- data/spec/ffi/errno_spec.rb +13 -0
- data/spec/ffi/library_spec.rb +144 -0
- data/spec/ffi/managed_struct_spec.rb +56 -0
- data/spec/ffi/number_spec.rb +231 -0
- data/spec/ffi/pointer_spec.rb +195 -0
- data/spec/ffi/rbx/attach_function_spec.rb +27 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
- data/spec/ffi/rbx/spec_helper.rb +1 -0
- data/spec/ffi/rbx/struct_spec.rb +13 -0
- data/spec/ffi/spec_helper.rb +17 -0
- data/spec/ffi/string_spec.rb +103 -0
- data/spec/ffi/struct_callback_spec.rb +41 -0
- data/spec/ffi/struct_initialize_spec.rb +30 -0
- data/spec/ffi/struct_spec.rb +476 -0
- data/spec/ffi/typedef_spec.rb +48 -0
- data/spec/ffi/union_spec.rb +60 -0
- data/spec/ffi/variadic_spec.rb +84 -0
- data/spec/spec.opts +4 -0
- metadata +375 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
module FFI
|
2
|
+
#
|
3
|
+
# FFI::ManagedStruct allows custom garbage-collection of your FFI::Structs.
|
4
|
+
#
|
5
|
+
# The typical use case would be when interacting with a library
|
6
|
+
# that has a nontrivial memory management design, such as a linked
|
7
|
+
# list or a binary tree.
|
8
|
+
#
|
9
|
+
# When the Struct instance is garbage collected, FFI::ManagedStruct will
|
10
|
+
# invoke the class's release() method during object finalization.
|
11
|
+
#
|
12
|
+
# Example usage:
|
13
|
+
# module MyLibrary
|
14
|
+
# ffi_lib "libmylibrary"
|
15
|
+
# attach_function :new_dlist, [], :pointer
|
16
|
+
# attach_function :destroy_dlist, [:pointer], :void
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# class DoublyLinkedList < FFI::ManagedStruct
|
20
|
+
# @@@
|
21
|
+
# struct do |s|
|
22
|
+
# s.name 'struct dlist'
|
23
|
+
# s.include 'dlist.h'
|
24
|
+
# s.field :head, :pointer
|
25
|
+
# s.field :tail, :pointer
|
26
|
+
# end
|
27
|
+
# @@@
|
28
|
+
#
|
29
|
+
# def self.release ptr
|
30
|
+
# MyLibrary.destroy_dlist(ptr)
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# begin
|
35
|
+
# ptr = DoublyLinkedList.new(MyLibrary.new_dlist)
|
36
|
+
# # do something with the list
|
37
|
+
# end
|
38
|
+
# # struct is out of scope, and will be GC'd using DoublyLinkedList#release
|
39
|
+
#
|
40
|
+
#
|
41
|
+
class ManagedStruct < FFI::Struct
|
42
|
+
|
43
|
+
# call-seq:
|
44
|
+
# ManagedStruct.new(pointer)
|
45
|
+
# ManagedStruct.new
|
46
|
+
#
|
47
|
+
# When passed a pointer, create a new ManagedStruct which will invoke the class method release() on
|
48
|
+
def initialize(pointer=nil)
|
49
|
+
raise NoMethodError, "release() not implemented for class #{self}" unless self.class.respond_to? :release
|
50
|
+
raise ArgumentError, "Must supply a pointer to memory for the Struct" unless pointer
|
51
|
+
super FFI::AutoPointer.new(pointer, self.class.method(:release))
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'ffi/pointer'
|
2
|
+
module FFI
|
3
|
+
class MemoryPointer
|
4
|
+
# call-seq:
|
5
|
+
# MemoryPointer.new(num) => MemoryPointer instance of <i>num</i> bytes
|
6
|
+
# MemoryPointer.new(sym) => MemoryPointer instance with number
|
7
|
+
# of bytes need by FFI type <i>sym</i>
|
8
|
+
# MemoryPointer.new(obj) => MemoryPointer instance with number
|
9
|
+
# of <i>obj.size</i> bytes
|
10
|
+
# MemoryPointer.new(sym, count) => MemoryPointer instance with number
|
11
|
+
# of bytes need by length-<i>count</i> array
|
12
|
+
# of FFI type <i>sym</i>
|
13
|
+
# MemoryPointer.new(obj, count) => MemoryPointer instance with number
|
14
|
+
# of bytes need by length-<i>count</i> array
|
15
|
+
# of <i>obj.size</i> bytes
|
16
|
+
# MemoryPointer.new(arg) { |p| ... }
|
17
|
+
#
|
18
|
+
# Both forms create a MemoryPointer instance. The number of bytes to
|
19
|
+
# allocate is either specified directly or by passing an FFI type, which
|
20
|
+
# specifies the number of bytes needed for that type.
|
21
|
+
#
|
22
|
+
# The form without a block returns the MemoryPointer instance. The form
|
23
|
+
# with a block yields the MemoryPointer instance and frees the memory
|
24
|
+
# when the block returns. The value returned is the value of the block.
|
25
|
+
|
26
|
+
# def self.new(type, count=nil, clear=true)
|
27
|
+
# size = if type.kind_of? Fixnum
|
28
|
+
# type
|
29
|
+
# elsif type.kind_of? Symbol
|
30
|
+
# FFI.type_size(type)
|
31
|
+
# else
|
32
|
+
# type.size
|
33
|
+
# end
|
34
|
+
# ptr = self.__allocate(size, count, clear)
|
35
|
+
# ptr.type_size = size
|
36
|
+
# if block_given?
|
37
|
+
# begin
|
38
|
+
# value = yield ptr
|
39
|
+
# ensure
|
40
|
+
# ptr.free
|
41
|
+
# end
|
42
|
+
# value
|
43
|
+
# else
|
44
|
+
# ptr
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
def self.from_string(s)
|
48
|
+
ptr = self.new(s.length + 1, 1, false)
|
49
|
+
ptr.put_string(0, s)
|
50
|
+
ptr
|
51
|
+
end
|
52
|
+
# Indicates how many bytes the type that the pointer is cast as uses.
|
53
|
+
# attr_accessor :type_size
|
54
|
+
|
55
|
+
# Access the MemoryPointer like a C array, accessing the +which+ number
|
56
|
+
# element in memory. The position of the element is calculate from
|
57
|
+
# +@type_size+ and +which+. A new MemoryPointer object is returned, which
|
58
|
+
# points to the address of the element.
|
59
|
+
#
|
60
|
+
# Example:
|
61
|
+
# ptr = MemoryPointer.new(:int, 20)
|
62
|
+
# new_ptr = ptr[9]
|
63
|
+
#
|
64
|
+
# c-equiv:
|
65
|
+
# int *ptr = (int*)malloc(sizeof(int) * 20);
|
66
|
+
# int *new_ptr;
|
67
|
+
# new_ptr = &ptr[9];
|
68
|
+
#
|
69
|
+
# def [](which)
|
70
|
+
# self + (which * type_size)
|
71
|
+
# end
|
72
|
+
end
|
73
|
+
end
|
data/lib/ffi/platform.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
module FFI
|
3
|
+
class PlatformError < FFI::NativeError; end
|
4
|
+
|
5
|
+
module Platform
|
6
|
+
OS = case Config::CONFIG['host_os'].downcase
|
7
|
+
when /linux/
|
8
|
+
"linux"
|
9
|
+
when /darwin/
|
10
|
+
"darwin"
|
11
|
+
when /freebsd/
|
12
|
+
"freebsd"
|
13
|
+
when /openbsd/
|
14
|
+
"openbsd"
|
15
|
+
when /sunos|solaris/
|
16
|
+
"solaris"
|
17
|
+
when /win|mingw/
|
18
|
+
"windows"
|
19
|
+
else
|
20
|
+
raise FFI::PlatformError, "Unknown operating system: #{Config::CONFIG['host_os']}"
|
21
|
+
end
|
22
|
+
ARCH = case CPU.downcase
|
23
|
+
when /amd64|x86_64/
|
24
|
+
"x86_64"
|
25
|
+
when /i?86|x86|i86pc/
|
26
|
+
"i386"
|
27
|
+
when /ppc|powerpc/
|
28
|
+
"powerpc"
|
29
|
+
else
|
30
|
+
raise FFI::PlatformError, "Unknown cpu architecture: #{ARCH_}"
|
31
|
+
end
|
32
|
+
private
|
33
|
+
def self.is_os(os)
|
34
|
+
OS == os
|
35
|
+
end
|
36
|
+
|
37
|
+
NAME = "#{ARCH}-#{OS}"
|
38
|
+
IS_LINUX = is_os("linux")
|
39
|
+
IS_MAC = is_os("darwin")
|
40
|
+
IS_FREEBSD = is_os("freebsd")
|
41
|
+
IS_OPENBSD = is_os("openbsd")
|
42
|
+
IS_WINDOWS = is_os("windows")
|
43
|
+
IS_BSD = IS_MAC || IS_FREEBSD || IS_OPENBSD
|
44
|
+
CONF_DIR = File.dirname(__FILE__)
|
45
|
+
public
|
46
|
+
LIBC = if IS_WINDOWS
|
47
|
+
"msvcrt"
|
48
|
+
elsif IS_LINUX
|
49
|
+
"libc.so.6"
|
50
|
+
else
|
51
|
+
"c"
|
52
|
+
end
|
53
|
+
LIBPREFIX = IS_WINDOWS ? '' : 'lib'
|
54
|
+
LIBSUFFIX = case OS
|
55
|
+
when /darwin/
|
56
|
+
'dylib'
|
57
|
+
when /linux|bsd|solaris/
|
58
|
+
'so'
|
59
|
+
when /win/
|
60
|
+
'dll'
|
61
|
+
else
|
62
|
+
raise PlatformError, "Cannot determine shared library extension for #{OS}"
|
63
|
+
end
|
64
|
+
def self.bsd?
|
65
|
+
IS_BSD
|
66
|
+
end
|
67
|
+
def self.windows?
|
68
|
+
IS_WINDOWS
|
69
|
+
end
|
70
|
+
def self.mac?
|
71
|
+
IS_MAC
|
72
|
+
end
|
73
|
+
def self.unix?
|
74
|
+
!IS_WINDOWS
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
data/lib/ffi/pointer.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'ffi/platform'
|
2
|
+
module FFI
|
3
|
+
class Pointer
|
4
|
+
SIZE = Platform::ADDRESS_SIZE / 8
|
5
|
+
|
6
|
+
# Return the size of a pointer on the current platform, in bytes
|
7
|
+
def self.size
|
8
|
+
SIZE
|
9
|
+
end
|
10
|
+
# Write +obj+ as a C int at the memory pointed to.
|
11
|
+
def write_int(obj)
|
12
|
+
put_int32(0, obj)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Read a C int from the memory pointed to.
|
16
|
+
def read_int
|
17
|
+
get_int32(0)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Write +obj+ as a C long at the memory pointed to.
|
21
|
+
def write_long(obj)
|
22
|
+
put_long(0, obj)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Read a C long from the memory pointed to.
|
26
|
+
def read_long
|
27
|
+
get_long(0)
|
28
|
+
end
|
29
|
+
# Write +obj+ as a C long long at the memory pointed to.
|
30
|
+
def write_long_long(obj)
|
31
|
+
put_int64(0, obj)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Read a C long long from the memory pointed to.
|
35
|
+
def read_long_long
|
36
|
+
get_int64(0)
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_pointer
|
40
|
+
get_pointer(0)
|
41
|
+
end
|
42
|
+
def write_pointer(ptr)
|
43
|
+
put_pointer(0, ptr)
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_float
|
47
|
+
get_float32(0)
|
48
|
+
end
|
49
|
+
def write_float(obj)
|
50
|
+
put_float32(0, obj)
|
51
|
+
end
|
52
|
+
|
53
|
+
def read_string(len=nil)
|
54
|
+
if len
|
55
|
+
get_bytes(0, len)
|
56
|
+
else
|
57
|
+
get_string(0)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
def read_string_length(len)
|
61
|
+
get_bytes(0, len)
|
62
|
+
end
|
63
|
+
def read_string_to_null
|
64
|
+
get_string(0)
|
65
|
+
end
|
66
|
+
def write_string_length(str, len)
|
67
|
+
put_bytes(0, str, 0, len)
|
68
|
+
end
|
69
|
+
def write_string(str, len=nil)
|
70
|
+
len = str.size unless len
|
71
|
+
# Write the string data without NUL termination
|
72
|
+
put_bytes(0, str, 0, len)
|
73
|
+
end
|
74
|
+
def read_array_of_type(type, reader, length)
|
75
|
+
ary = []
|
76
|
+
size = FFI.type_size(type)
|
77
|
+
tmp = self
|
78
|
+
length.times { |j|
|
79
|
+
ary << tmp.send(reader)
|
80
|
+
tmp += size unless j == length-1 # avoid OOB
|
81
|
+
}
|
82
|
+
ary
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_array_of_type(type, writer, ary)
|
86
|
+
size = FFI.type_size(type)
|
87
|
+
tmp = self
|
88
|
+
ary.each_with_index {|i, j|
|
89
|
+
tmp.send(writer, i)
|
90
|
+
tmp += size unless j == ary.length-1 # avoid OOB
|
91
|
+
}
|
92
|
+
self
|
93
|
+
end
|
94
|
+
def read_array_of_int(length)
|
95
|
+
get_array_of_int32(0, length)
|
96
|
+
end
|
97
|
+
|
98
|
+
def write_array_of_int(ary)
|
99
|
+
put_array_of_int32(0, ary)
|
100
|
+
end
|
101
|
+
|
102
|
+
def read_array_of_long(length)
|
103
|
+
get_array_of_long(0, length)
|
104
|
+
end
|
105
|
+
|
106
|
+
def write_array_of_long(ary)
|
107
|
+
put_array_of_long(0, ary)
|
108
|
+
end
|
109
|
+
|
110
|
+
def read_array_of_pointer(length)
|
111
|
+
read_array_of_type(:pointer, :read_pointer, length)
|
112
|
+
end
|
113
|
+
|
114
|
+
def write_array_of_pointer(ary)
|
115
|
+
write_array_of_type(:pointer, :write_pointer, ary)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
data/lib/ffi/struct.rb
ADDED
@@ -0,0 +1,354 @@
|
|
1
|
+
require 'ffi/platform'
|
2
|
+
module FFI
|
3
|
+
|
4
|
+
class StructLayout
|
5
|
+
attr_reader :size, :align
|
6
|
+
|
7
|
+
def members
|
8
|
+
@field_names
|
9
|
+
end
|
10
|
+
def offsets
|
11
|
+
@fields.map { |name, field| [name, field.offset] }.sort { |a, b| a[1] <=> b[1] }
|
12
|
+
end
|
13
|
+
def offset_of(field_name)
|
14
|
+
@fields[field_name].offset
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class StructLayoutBuilder
|
19
|
+
class Field
|
20
|
+
def size
|
21
|
+
self.class.size
|
22
|
+
end
|
23
|
+
def align
|
24
|
+
self.class.align
|
25
|
+
end
|
26
|
+
def offset
|
27
|
+
@off
|
28
|
+
end
|
29
|
+
def self.size
|
30
|
+
const_get(:SIZE)
|
31
|
+
end
|
32
|
+
def self.align
|
33
|
+
const_get(:ALIGN)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.struct_field_class_from(type)
|
38
|
+
klass_name = type.name.split('::').last
|
39
|
+
code = <<-code
|
40
|
+
class StructField_#{klass_name} < Field
|
41
|
+
@info = #{type}
|
42
|
+
class << self
|
43
|
+
attr_reader :info
|
44
|
+
def size
|
45
|
+
#{type.size}
|
46
|
+
end
|
47
|
+
def align
|
48
|
+
#{type.align}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
def get(ptr)
|
52
|
+
self.class.info.new(ptr + @off)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
StructField_#{klass_name}
|
56
|
+
code
|
57
|
+
self.module_eval(code)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.array_field_class_from(type, num)
|
61
|
+
klass_name = type.name.split('::').last
|
62
|
+
code = <<-code
|
63
|
+
class ArrayField_#{klass_name}_#{num} < Field
|
64
|
+
@info = #{type}
|
65
|
+
@num = #{num}
|
66
|
+
class << self
|
67
|
+
attr_reader :info, :num
|
68
|
+
def size
|
69
|
+
#{type.size} * #{num}
|
70
|
+
end
|
71
|
+
def align
|
72
|
+
#{type.align}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
def get(ptr)
|
76
|
+
@array ? @array : get_array_data(ptr)
|
77
|
+
end
|
78
|
+
private
|
79
|
+
def get_array_data(ptr)
|
80
|
+
@array = FFI::Struct::Array.new(ptr + @off, self.class.info, self.class.num)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
ArrayField_#{klass_name}_#{num}
|
84
|
+
code
|
85
|
+
self.module_eval(code)
|
86
|
+
end
|
87
|
+
|
88
|
+
class CallbackField < Field
|
89
|
+
def self.size
|
90
|
+
FFI::Type::POINTER.size
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.align
|
94
|
+
FFI::Type::POINTER.alignment
|
95
|
+
end
|
96
|
+
|
97
|
+
def put(ptr, proc)
|
98
|
+
ptr.put_callback(@off, proc, @info)
|
99
|
+
end
|
100
|
+
|
101
|
+
def get(ptr)
|
102
|
+
raise ArgumentError, "Cannot get callback fields"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize
|
107
|
+
@field_names = []
|
108
|
+
@fields = {}
|
109
|
+
@size = 0
|
110
|
+
@min_align = 1
|
111
|
+
end
|
112
|
+
|
113
|
+
def native_field_class_from(type)
|
114
|
+
case type
|
115
|
+
when :char, NativeType::INT8
|
116
|
+
Signed8
|
117
|
+
when :uchar, NativeType::UINT8
|
118
|
+
Unsigned8
|
119
|
+
when :short, NativeType::INT16
|
120
|
+
Signed16
|
121
|
+
when :ushort, NativeType::UINT16
|
122
|
+
Unsigned16
|
123
|
+
when :long, NativeType::LONG
|
124
|
+
FFI::Platform::LONG_SIZE == 32 ? Signed32 : Signed64
|
125
|
+
when :ulong, NativeType::ULONG
|
126
|
+
FFI::Platform::LONG_SIZE == 32 ? Unsigned32 : Unsigned64
|
127
|
+
when :int, NativeType::INT32
|
128
|
+
Signed32
|
129
|
+
when :uint, NativeType::UINT32
|
130
|
+
Unsigned32
|
131
|
+
when :long_long, NativeType::INT64
|
132
|
+
Signed64
|
133
|
+
when :ulong_long, NativeType::UINT64
|
134
|
+
Unsigned64
|
135
|
+
when :float, NativeType::FLOAT32
|
136
|
+
FloatField
|
137
|
+
when :double, NativeType::FLOAT64
|
138
|
+
DoubleField
|
139
|
+
when :pointer, NativeType::POINTER
|
140
|
+
PointerField
|
141
|
+
when :string, NativeType::STRING
|
142
|
+
StringField
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def callback_field_class_from(type)
|
147
|
+
return CallbackField, type if type.is_a?(FFI::CallbackInfo)
|
148
|
+
end
|
149
|
+
|
150
|
+
def struct_field_class_from(type)
|
151
|
+
self.class.struct_field_class_from(type) if type.is_a?(Class) and type < FFI::Struct
|
152
|
+
end
|
153
|
+
|
154
|
+
def array_field_class_from(type)
|
155
|
+
self.class.array_field_class_from(field_class_from(type[0]), type[1]) if type.is_a?(Array)
|
156
|
+
end
|
157
|
+
|
158
|
+
def field_class_from(type)
|
159
|
+
field_class = native_field_class_from(type) ||
|
160
|
+
callback_field_class_from(type) ||
|
161
|
+
array_field_class_from(type) ||
|
162
|
+
struct_field_class_from(type)
|
163
|
+
field_class or raise ArgumentError, "Unknown type: #{type}"
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_field(name, type, offset = nil)
|
167
|
+
field_class, info = field_class_from(type)
|
168
|
+
off = calc_alignment_of(field_class, offset)
|
169
|
+
calc_current_size(off, field_class.size)
|
170
|
+
@field_names << name
|
171
|
+
@fields[name] = field_class.new(off, info)
|
172
|
+
@min_align = field_class.align if field_class.align > @min_align
|
173
|
+
end
|
174
|
+
|
175
|
+
def build
|
176
|
+
StructLayout.new(@field_names, @fields, align(@size, @min_align), @min_align)
|
177
|
+
end
|
178
|
+
|
179
|
+
def align(offset, align)
|
180
|
+
align + ((offset - 1) & ~(align - 1))
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
def calc_alignment_of(field_class, offset)
|
185
|
+
offset ? offset.to_i : align(@size, field_class.align)
|
186
|
+
end
|
187
|
+
def calc_current_size(offset, size)
|
188
|
+
@size = offset + size
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class Struct
|
193
|
+
class Array
|
194
|
+
include Enumerable
|
195
|
+
|
196
|
+
def initialize(ptr, type, num)
|
197
|
+
@pointer, @type, @num = ptr, type, num
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_ptr
|
201
|
+
@pointer
|
202
|
+
end
|
203
|
+
|
204
|
+
def to_a
|
205
|
+
get_array_data(@pointer)
|
206
|
+
end
|
207
|
+
|
208
|
+
def size
|
209
|
+
@num * @type.size
|
210
|
+
end
|
211
|
+
|
212
|
+
def each(&blk)
|
213
|
+
to_a.each(&blk)
|
214
|
+
end
|
215
|
+
|
216
|
+
private
|
217
|
+
def get_array_data(ptr)
|
218
|
+
(0..@num - 1).inject([]) do |array, index|
|
219
|
+
array << @type.new(0).get(ptr + index * @type.size)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.size
|
225
|
+
@size
|
226
|
+
end
|
227
|
+
|
228
|
+
def self.members
|
229
|
+
@layout.members
|
230
|
+
end
|
231
|
+
|
232
|
+
def self.align
|
233
|
+
@layout.align
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.offsets
|
237
|
+
@layout.offsets
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.offset_of(field_name)
|
241
|
+
@layout.offset_of(field_name)
|
242
|
+
end
|
243
|
+
|
244
|
+
def size
|
245
|
+
self.class.size
|
246
|
+
end
|
247
|
+
|
248
|
+
def align
|
249
|
+
self.class.align
|
250
|
+
end
|
251
|
+
|
252
|
+
def members
|
253
|
+
layout.members
|
254
|
+
end
|
255
|
+
|
256
|
+
def values
|
257
|
+
layout.members.map { |m| self[m] }
|
258
|
+
end
|
259
|
+
def offsets
|
260
|
+
self.class.offsets
|
261
|
+
end
|
262
|
+
|
263
|
+
def offset_of(field_name)
|
264
|
+
self.class.offset_of(field_name)
|
265
|
+
end
|
266
|
+
|
267
|
+
def clear
|
268
|
+
pointer.clear
|
269
|
+
self
|
270
|
+
end
|
271
|
+
|
272
|
+
def to_ptr
|
273
|
+
pointer
|
274
|
+
end
|
275
|
+
|
276
|
+
def self.in
|
277
|
+
:buffer_in
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.out
|
281
|
+
:buffer_out
|
282
|
+
end
|
283
|
+
|
284
|
+
protected
|
285
|
+
|
286
|
+
def self.callback(params, ret)
|
287
|
+
mod = enclosing_module
|
288
|
+
FFI::CallbackInfo.new(find_type(ret, mod), params.map { |e| find_type(e, mod) })
|
289
|
+
end
|
290
|
+
|
291
|
+
private
|
292
|
+
|
293
|
+
def self.builder
|
294
|
+
StructLayoutBuilder.new
|
295
|
+
end
|
296
|
+
|
297
|
+
def self.enclosing_module
|
298
|
+
begin
|
299
|
+
mod = self.name.split("::")[0..-2].inject(Object) { |obj, c| obj.const_get(c) }
|
300
|
+
mod.respond_to?(:find_type) ? mod : nil
|
301
|
+
rescue Exception => ex
|
302
|
+
nil
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def self.is_a_struct?(type)
|
307
|
+
type.is_a?(Class) and type < Struct
|
308
|
+
end
|
309
|
+
|
310
|
+
def self.find_type(type, mod = nil)
|
311
|
+
return type if is_a_struct?(type) or type.is_a?(::Array)
|
312
|
+
mod ? mod.find_type(type) : FFI.find_type(type)
|
313
|
+
end
|
314
|
+
|
315
|
+
def self.hash_layout(spec)
|
316
|
+
raise "Ruby version not supported" if RUBY_VERSION =~ /1.8.*/
|
317
|
+
builder = self.builder
|
318
|
+
mod = enclosing_module
|
319
|
+
spec[0].each do |name,type|
|
320
|
+
builder.add_field(name, find_type(type, mod))
|
321
|
+
end
|
322
|
+
builder.build
|
323
|
+
end
|
324
|
+
|
325
|
+
def self.array_layout(spec)
|
326
|
+
builder = self.builder
|
327
|
+
mod = enclosing_module
|
328
|
+
i = 0
|
329
|
+
while i < spec.size
|
330
|
+
name, type = spec[i, 2]
|
331
|
+
i += 2
|
332
|
+
code = find_type(type, mod)
|
333
|
+
# If the next param is a Fixnum, it specifies the offset
|
334
|
+
if spec[i].kind_of?(Fixnum)
|
335
|
+
offset = spec[i]
|
336
|
+
i += 1
|
337
|
+
builder.add_field(name, code, offset)
|
338
|
+
else
|
339
|
+
builder.add_field(name, code)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
builder.build
|
343
|
+
end
|
344
|
+
|
345
|
+
public
|
346
|
+
def self.layout(*spec)
|
347
|
+
return @layout if spec.size == 0
|
348
|
+
cspec = spec[0].kind_of?(Hash) ? hash_layout(spec) : array_layout(spec)
|
349
|
+
@layout = cspec unless self == FFI::Struct
|
350
|
+
@size = cspec.size
|
351
|
+
return cspec
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|