ffi 0.5.0-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/LICENSE +51 -0
- data/README.rdoc +69 -0
- data/Rakefile +191 -0
- data/ext/ffi_c/AbstractMemory.c +489 -0
- data/ext/ffi_c/AbstractMemory.h +160 -0
- data/ext/ffi_c/ArrayType.c +129 -0
- data/ext/ffi_c/ArrayType.h +58 -0
- data/ext/ffi_c/AutoPointer.c +61 -0
- data/ext/ffi_c/AutoPointer.h +18 -0
- data/ext/ffi_c/Buffer.c +187 -0
- data/ext/ffi_c/Call.c +853 -0
- data/ext/ffi_c/Call.h +86 -0
- data/ext/ffi_c/ClosurePool.c +302 -0
- data/ext/ffi_c/ClosurePool.h +29 -0
- data/ext/ffi_c/DynamicLibrary.c +216 -0
- data/ext/ffi_c/DynamicLibrary.h +22 -0
- data/ext/ffi_c/Function.c +478 -0
- data/ext/ffi_c/Function.h +80 -0
- data/ext/ffi_c/FunctionInfo.c +221 -0
- data/ext/ffi_c/LastError.c +159 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +178 -0
- data/ext/ffi_c/MemoryPointer.h +20 -0
- data/ext/ffi_c/MethodHandle.c +346 -0
- data/ext/ffi_c/MethodHandle.h +53 -0
- data/ext/ffi_c/Platform.c +59 -0
- data/ext/ffi_c/Platform.h +16 -0
- data/ext/ffi_c/Pointer.c +224 -0
- data/ext/ffi_c/Pointer.h +49 -0
- data/ext/ffi_c/Struct.c +770 -0
- data/ext/ffi_c/Struct.h +80 -0
- data/ext/ffi_c/StructByValue.c +140 -0
- data/ext/ffi_c/StructByValue.h +53 -0
- data/ext/ffi_c/StructLayout.c +450 -0
- data/ext/ffi_c/Type.c +329 -0
- data/ext/ffi_c/Type.h +57 -0
- data/ext/ffi_c/Types.c +103 -0
- data/ext/ffi_c/Types.h +85 -0
- data/ext/ffi_c/Variadic.c +260 -0
- data/ext/ffi_c/compat.h +72 -0
- data/ext/ffi_c/endian.h +40 -0
- data/ext/ffi_c/extconf.rb +30 -0
- data/ext/ffi_c/ffi.c +82 -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 +26 -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 +99 -0
- data/lib/ffi/io.rb +21 -0
- data/lib/ffi/library.rb +218 -0
- data/lib/ffi/managedstruct.rb +55 -0
- data/lib/ffi/memorypointer.rb +73 -0
- data/lib/ffi/platform.rb +88 -0
- data/lib/ffi/pointer.rb +119 -0
- data/lib/ffi/struct.rb +183 -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 +12 -0
- data/lib/ffi/variadic.rb +25 -0
- data/spec/ffi/bool_spec.rb +24 -0
- data/spec/ffi/buffer_spec.rb +202 -0
- data/spec/ffi/callback_spec.rb +591 -0
- data/spec/ffi/enum_spec.rb +164 -0
- data/spec/ffi/errno_spec.rb +13 -0
- data/spec/ffi/function_spec.rb +73 -0
- data/spec/ffi/library_spec.rb +148 -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 +64 -0
- data/spec/ffi/struct_initialize_spec.rb +30 -0
- data/spec/ffi/struct_spec.rb +529 -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 +396 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
3
|
+
|
4
|
+
module CTest
|
5
|
+
extend FFI::Library
|
6
|
+
|
7
|
+
attach_function :strcat, [:pointer, :pointer], :pointer
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "MemoryPointer" do
|
11
|
+
it "makes a pointer from a string" do
|
12
|
+
m = FFI::MemoryPointer.from_string("FFI is Awesome")
|
13
|
+
m.type_size.should == 15
|
14
|
+
end
|
15
|
+
|
16
|
+
it "reads back a string" do
|
17
|
+
m = FFI::MemoryPointer.from_string("FFI is Awesome")
|
18
|
+
m.read_string.should == "FFI is Awesome"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "makes a pointer for a certain number of bytes" do
|
22
|
+
m = FFI::MemoryPointer.new(8)
|
23
|
+
m.write_array_of_int([1,2])
|
24
|
+
m.read_array_of_int(2).should == [1,2]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "allows access to an element of the pointer (as an array)" do
|
28
|
+
m = FFI::MemoryPointer.new(:int, 2)
|
29
|
+
m.write_array_of_int([1,2])
|
30
|
+
m[0].read_int.should == 1
|
31
|
+
m[1].read_int.should == 2
|
32
|
+
end
|
33
|
+
|
34
|
+
it "allows writing as an int" do
|
35
|
+
m = FFI::MemoryPointer.new(:int)
|
36
|
+
m.write_int(1)
|
37
|
+
m.read_int.should == 1
|
38
|
+
end
|
39
|
+
|
40
|
+
it "allows writing as a long" do
|
41
|
+
m = FFI::MemoryPointer.new(:long)
|
42
|
+
m.write_long(10)
|
43
|
+
m.read_long.should == 10
|
44
|
+
end
|
45
|
+
|
46
|
+
it "raises an error if you try putting a long into a pointer of size 1" do
|
47
|
+
m = FFI::MemoryPointer.new(1)
|
48
|
+
lambda { m.write_long(10) }.should raise_error
|
49
|
+
end
|
50
|
+
|
51
|
+
it "raises an error if you try putting an int into a pointer of size 1" do
|
52
|
+
m = FFI::MemoryPointer.new(1)
|
53
|
+
lambda { m.write_int(10) }.should raise_error
|
54
|
+
end
|
55
|
+
# it "does not raise IndexError for opaque pointers" do
|
56
|
+
# m = FFI::MemoryPointer.new(8)
|
57
|
+
# p2 = FFI::MemoryPointer.new(1024)
|
58
|
+
# m.write_long(p2.address)
|
59
|
+
# p = m.read_pointer
|
60
|
+
# lambda { p.write_int(10) }.should_not raise_error
|
61
|
+
# end
|
62
|
+
|
63
|
+
it "makes a pointer for a certain type" do
|
64
|
+
m = FFI::MemoryPointer.new(:int)
|
65
|
+
m.write_int(10)
|
66
|
+
m.read_int.should == 10
|
67
|
+
end
|
68
|
+
|
69
|
+
it "makes a memory pointer for a number of a certain type" do
|
70
|
+
m = FFI::MemoryPointer.new(:int, 2)
|
71
|
+
m.write_array_of_int([1,2])
|
72
|
+
m.read_array_of_int(2).should == [1,2]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "makes a pointer for an object responding to #size" do
|
76
|
+
m = FFI::MemoryPointer.new(Struct.new(:size).new(8))
|
77
|
+
m.write_array_of_int([1,2])
|
78
|
+
m.read_array_of_int(2).should == [1,2]
|
79
|
+
end
|
80
|
+
|
81
|
+
it "makes a pointer for a number of an object responding to #size" do
|
82
|
+
m = FFI::MemoryPointer.new(Struct.new(:size).new(4), 2)
|
83
|
+
m.write_array_of_int([1,2])
|
84
|
+
m.read_array_of_int(2).should == [1,2]
|
85
|
+
end
|
86
|
+
it "MemoryPointer#address returns correct value" do
|
87
|
+
m = FFI::MemoryPointer.new(:long_long)
|
88
|
+
magic = 0x12345678
|
89
|
+
m.write_long(magic)
|
90
|
+
m.read_pointer.address.should == magic
|
91
|
+
end
|
92
|
+
it "MemoryPointer#null? returns true for zero value" do
|
93
|
+
m = FFI::MemoryPointer.new(:long_long)
|
94
|
+
m.write_long(0)
|
95
|
+
m.read_pointer.null?.should == true
|
96
|
+
end
|
97
|
+
it "MemoryPointer#null? returns false for non-zero value" do
|
98
|
+
m = FFI::MemoryPointer.new(:long_long)
|
99
|
+
m.write_long(0x12345678)
|
100
|
+
m.read_pointer.null?.should == false
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
class Timeval < FFI::Struct
|
4
|
+
layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
|
5
|
+
end
|
6
|
+
|
7
|
+
describe FFI::Struct do
|
8
|
+
it "allows setting fields" do
|
9
|
+
t = Timeval.new
|
10
|
+
t[:tv_sec] = 12
|
11
|
+
t[:tv_sec].should == 12
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
if ENV["MRI_FFI"]
|
6
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib"),
|
7
|
+
File.join(File.dirname(__FILE__), "..", "..", "build", "#{Config::CONFIG['host_cpu''arch']}", "ffi_c", RUBY_VERSION)
|
8
|
+
end
|
9
|
+
require "ffi"
|
10
|
+
|
11
|
+
module TestLibrary
|
12
|
+
PATH = "build/libtest.#{FFI::Platform::LIBSUFFIX}"
|
13
|
+
end
|
14
|
+
module LibTest
|
15
|
+
extend FFI::Library
|
16
|
+
ffi_lib TestLibrary::PATH
|
17
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
describe "String tests" do
|
3
|
+
include FFI
|
4
|
+
module StrLibTest
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib TestLibrary::PATH
|
7
|
+
attach_function :ptr_ret_pointer, [ :pointer, :int], :string
|
8
|
+
attach_function :string_equals, [ :string, :string ], :int
|
9
|
+
attach_function :string_dummy, [ :string ], :void
|
10
|
+
attach_function :string_null, [ ], :string
|
11
|
+
end
|
12
|
+
it "MemoryPointer#get_string returns a tainted string" do
|
13
|
+
mp = MemoryPointer.new 1024
|
14
|
+
mp.put_string(0, "test\0")
|
15
|
+
str = mp.get_string(0)
|
16
|
+
str.tainted?.should == true
|
17
|
+
end
|
18
|
+
it "String returned by a method is tainted" do
|
19
|
+
mp = MemoryPointer.new :pointer
|
20
|
+
sp = MemoryPointer.new 1024
|
21
|
+
sp.put_string(0, "test")
|
22
|
+
mp.put_pointer(0, sp)
|
23
|
+
str = StrLibTest.ptr_ret_pointer(mp, 0)
|
24
|
+
str.should == "test"
|
25
|
+
str.tainted?.should == true
|
26
|
+
end
|
27
|
+
it "Poison null byte raises error" do
|
28
|
+
s = "123\0abc"
|
29
|
+
lambda { StrLibTest.string_equals(s, s) }.should raise_error
|
30
|
+
end
|
31
|
+
it "Tainted String parameter should throw a SecurityError" do
|
32
|
+
$SAFE = 1
|
33
|
+
str = "test"
|
34
|
+
str.taint
|
35
|
+
begin
|
36
|
+
LibTest.string_equals(str, str).should == false
|
37
|
+
rescue SecurityError => e
|
38
|
+
end
|
39
|
+
end if false
|
40
|
+
it "casts nil as NULL pointer" do
|
41
|
+
StrLibTest.string_dummy(nil)
|
42
|
+
end
|
43
|
+
it "return nil for NULL char*" do
|
44
|
+
StrLibTest.string_null.should == nil
|
45
|
+
end
|
46
|
+
it "reads an array of strings until encountering a NULL pointer" do
|
47
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
48
|
+
ptrary = MemoryPointer.new(:pointer, 6)
|
49
|
+
ary = strings.inject([]) do |a, str|
|
50
|
+
f = MemoryPointer.new(1024)
|
51
|
+
f.put_string(0, str)
|
52
|
+
a << f
|
53
|
+
end
|
54
|
+
ary.insert(3, nil)
|
55
|
+
ptrary.write_array_of_pointer(ary)
|
56
|
+
ptrary.get_array_of_string(0).should == ["foo", "bar", "baz"]
|
57
|
+
end
|
58
|
+
it "reads an array of strings of the size specified, substituting nil when a pointer is NULL" do
|
59
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
60
|
+
ptrary = MemoryPointer.new(:pointer, 6)
|
61
|
+
ary = strings.inject([]) do |a, str|
|
62
|
+
f = MemoryPointer.new(1024)
|
63
|
+
f.put_string(0, str)
|
64
|
+
a << f
|
65
|
+
end
|
66
|
+
ary.insert(2, nil)
|
67
|
+
ptrary.write_array_of_pointer(ary)
|
68
|
+
ptrary.get_array_of_string(0, 4).should == ["foo", "bar", nil, "baz"]
|
69
|
+
end
|
70
|
+
it "reads an array of strings, taking a memory offset parameter" do
|
71
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
72
|
+
ptrary = MemoryPointer.new(:pointer, 5)
|
73
|
+
ary = strings.inject([]) do |a, str|
|
74
|
+
f = MemoryPointer.new(1024)
|
75
|
+
f.put_string(0, str)
|
76
|
+
a << f
|
77
|
+
end
|
78
|
+
ptrary.write_array_of_pointer(ary)
|
79
|
+
ptrary.get_array_of_string(2 * FFI.type_size(:pointer), 3).should == ["baz", "testing", "ffi"]
|
80
|
+
end
|
81
|
+
it "raises an IndexError when trying to read an array of strings out of bounds" do
|
82
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
83
|
+
ptrary = MemoryPointer.new(:pointer, 5)
|
84
|
+
ary = strings.inject([]) do |a, str|
|
85
|
+
f = MemoryPointer.new(1024)
|
86
|
+
f.put_string(0, str)
|
87
|
+
a << f
|
88
|
+
end
|
89
|
+
ptrary.write_array_of_pointer(ary)
|
90
|
+
lambda { ptrary.get_array_of_string(0, 6) }.should raise_error
|
91
|
+
end
|
92
|
+
it "raises an IndexError when trying to read an array of strings using a negative offset" do
|
93
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
94
|
+
ptrary = MemoryPointer.new(:pointer, 5)
|
95
|
+
ary = strings.inject([]) do |a, str|
|
96
|
+
f = MemoryPointer.new(1024)
|
97
|
+
f.put_string(0, str)
|
98
|
+
a << f
|
99
|
+
end
|
100
|
+
ptrary.write_array_of_pointer(ary)
|
101
|
+
lambda { ptrary.get_array_of_string(-1) }.should raise_error
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe FFI::Struct, ' with inline callback functions' do
|
4
|
+
it 'should be able to define inline callback field' do
|
5
|
+
module CallbackMember
|
6
|
+
extend FFI::Library
|
7
|
+
ffi_lib TestLibrary::PATH
|
8
|
+
DUMMY_CB = callback :dummy_cb, [ :int ], :int
|
9
|
+
class TestStruct < FFI::Struct
|
10
|
+
layout \
|
11
|
+
:add, callback([ :int, :int ], :int),
|
12
|
+
:sub, callback([ :int, :int ], :int),
|
13
|
+
:cb_with_cb_parameter, callback([ DUMMY_CB, :int ], :int)
|
14
|
+
end
|
15
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
16
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
17
|
+
end
|
18
|
+
end
|
19
|
+
it 'should take methods as callbacks' do
|
20
|
+
module CallbackMember
|
21
|
+
extend FFI::Library
|
22
|
+
ffi_lib TestLibrary::PATH
|
23
|
+
class TestStruct < FFI::Struct
|
24
|
+
layout \
|
25
|
+
:add, callback([ :int, :int ], :int),
|
26
|
+
:sub, callback([ :int, :int ], :int)
|
27
|
+
end
|
28
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
29
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
30
|
+
end
|
31
|
+
module StructCallbacks
|
32
|
+
def self.add a, b
|
33
|
+
a+b
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
ts = CallbackMember::TestStruct.new
|
38
|
+
ts[:add] = StructCallbacks.method(:add)
|
39
|
+
|
40
|
+
CallbackMember.struct_call_add_cb(ts, 1, 2).should == 3
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should return callable object from []' do
|
44
|
+
module CallbackMember
|
45
|
+
extend FFI::Library
|
46
|
+
ffi_lib TestLibrary::PATH
|
47
|
+
class TestStruct < FFI::Struct
|
48
|
+
layout \
|
49
|
+
:add, callback([ :int, :int ], :int),
|
50
|
+
:sub, callback([ :int, :int ], :int)
|
51
|
+
end
|
52
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
53
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
54
|
+
end
|
55
|
+
|
56
|
+
s = CallbackMember::TestStruct.new
|
57
|
+
add = Proc.new { |a,b| a+b}
|
58
|
+
s[:add] = add
|
59
|
+
fn = s[:add]
|
60
|
+
fn.respond_to?(:call).should be_true
|
61
|
+
fn.call(1, 2).should == 3
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe FFI::Struct, ' with an initialize function' do
|
4
|
+
it "should call the initialize function" do
|
5
|
+
class StructWithInitialize < FFI::Struct
|
6
|
+
layout :string, :string
|
7
|
+
attr_accessor :magic
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
self.magic = 42
|
11
|
+
end
|
12
|
+
end
|
13
|
+
StructWithInitialize.new.magic.should == 42
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe FFI::ManagedStruct, ' with an initialize function' do
|
18
|
+
it "should call the initialize function" do
|
19
|
+
class ManagedStructWithInitialize < FFI::ManagedStruct
|
20
|
+
layout :string, :string
|
21
|
+
attr_accessor :magic
|
22
|
+
def initialize
|
23
|
+
super MemoryPointer.new(:pointer).put_int(0, 0x1234).get_pointer(0)
|
24
|
+
self.magic = 42
|
25
|
+
end
|
26
|
+
def self.release;end
|
27
|
+
end
|
28
|
+
ManagedStructWithInitialize.new.magic.should == 42
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,529 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
describe "Struct tests" do
|
3
|
+
StructTypes = {
|
4
|
+
's8' => :char,
|
5
|
+
's16' => :short,
|
6
|
+
's32' => :int,
|
7
|
+
's64' => :long_long,
|
8
|
+
'long' => :long,
|
9
|
+
'f32' => :float,
|
10
|
+
'f64' => :double
|
11
|
+
}
|
12
|
+
module LibTest
|
13
|
+
extend FFI::Library
|
14
|
+
ffi_lib TestLibrary::PATH
|
15
|
+
attach_function :ptr_ret_pointer, [ :pointer, :int], :string
|
16
|
+
attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
|
17
|
+
attach_function :ptr_from_address, [ :ulong ], :pointer
|
18
|
+
attach_function :string_equals, [ :string, :string ], :int
|
19
|
+
[ 's8', 's16', 's32', 's64', 'f32', 'f64', 'long' ].each do |t|
|
20
|
+
attach_function "struct_align_#{t}", [ :pointer ], StructTypes[t]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
class PointerMember < FFI::Struct
|
24
|
+
layout :pointer, :pointer
|
25
|
+
end
|
26
|
+
class StringMember < FFI::Struct
|
27
|
+
layout :string, :string
|
28
|
+
end
|
29
|
+
it "Struct#[:pointer]" do
|
30
|
+
magic = 0x12345678
|
31
|
+
mp = FFI::MemoryPointer.new :long
|
32
|
+
mp.put_long(0, magic)
|
33
|
+
smp = FFI::MemoryPointer.new :pointer
|
34
|
+
smp.put_pointer(0, mp)
|
35
|
+
s = PointerMember.new smp
|
36
|
+
s[:pointer].should == mp
|
37
|
+
end
|
38
|
+
it "Struct#[:pointer].nil? for NULL value" do
|
39
|
+
magic = 0x12345678
|
40
|
+
mp = FFI::MemoryPointer.new :long
|
41
|
+
mp.put_long(0, magic)
|
42
|
+
smp = FFI::MemoryPointer.new :pointer
|
43
|
+
smp.put_pointer(0, nil)
|
44
|
+
s = PointerMember.new smp
|
45
|
+
s[:pointer].null?.should == true
|
46
|
+
end
|
47
|
+
it "Struct#[:pointer]=" do
|
48
|
+
magic = 0x12345678
|
49
|
+
mp = FFI::MemoryPointer.new :long
|
50
|
+
mp.put_long(0, magic)
|
51
|
+
smp = FFI::MemoryPointer.new :pointer
|
52
|
+
s = PointerMember.new smp
|
53
|
+
s[:pointer] = mp
|
54
|
+
smp.get_pointer(0).should == mp
|
55
|
+
end
|
56
|
+
it "Struct#[:pointer]=struct" do
|
57
|
+
magic = 0x12345678
|
58
|
+
smp = FFI::MemoryPointer.new :pointer
|
59
|
+
s = PointerMember.new smp
|
60
|
+
lambda { s[:pointer] = s }.should_not raise_error
|
61
|
+
end
|
62
|
+
it "Struct#[:pointer]=nil" do
|
63
|
+
smp = FFI::MemoryPointer.new :pointer
|
64
|
+
s = PointerMember.new smp
|
65
|
+
s[:pointer] = nil
|
66
|
+
smp.get_pointer(0).null?.should == true
|
67
|
+
end
|
68
|
+
it "Struct#[:string]" do
|
69
|
+
magic = "test"
|
70
|
+
mp = FFI::MemoryPointer.new 1024
|
71
|
+
mp.put_string(0, magic)
|
72
|
+
smp = FFI::MemoryPointer.new :pointer
|
73
|
+
smp.put_pointer(0, mp)
|
74
|
+
s = StringMember.new smp
|
75
|
+
s[:string].should == magic
|
76
|
+
end
|
77
|
+
it "Struct#[:string].nil? for NULL value" do
|
78
|
+
smp = FFI::MemoryPointer.new :pointer
|
79
|
+
smp.put_pointer(0, nil)
|
80
|
+
s = StringMember.new smp
|
81
|
+
s[:string].nil?.should == true
|
82
|
+
end
|
83
|
+
it "Struct#layout works with :name, :type pairs" do
|
84
|
+
class PairLayout < FFI::Struct
|
85
|
+
layout :a, :int, :b, :long_long
|
86
|
+
end
|
87
|
+
ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8)
|
88
|
+
PairLayout.size.should == (ll_off + 8)
|
89
|
+
mp = FFI::MemoryPointer.new(PairLayout.size)
|
90
|
+
s = PairLayout.new mp
|
91
|
+
s[:a] = 0x12345678
|
92
|
+
mp.get_int(0).should == 0x12345678
|
93
|
+
s[:b] = 0xfee1deadbeef
|
94
|
+
mp.get_int64(ll_off).should == 0xfee1deadbeef
|
95
|
+
end
|
96
|
+
it "Struct#layout works with :name, :type, offset tuples" do
|
97
|
+
class PairLayout < FFI::Struct
|
98
|
+
layout :a, :int, 0, :b, :long_long, 4
|
99
|
+
end
|
100
|
+
PairLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
101
|
+
mp = FFI::MemoryPointer.new(PairLayout.size)
|
102
|
+
s = PairLayout.new mp
|
103
|
+
s[:a] = 0x12345678
|
104
|
+
mp.get_int(0).should == 0x12345678
|
105
|
+
s[:b] = 0xfee1deadbeef
|
106
|
+
mp.get_int64(4).should == 0xfee1deadbeef
|
107
|
+
end
|
108
|
+
it "Struct#layout works with mixed :name,:type and :name,:type,offset" do
|
109
|
+
class MixedLayout < FFI::Struct
|
110
|
+
layout :a, :int, :b, :long_long, 4
|
111
|
+
end
|
112
|
+
MixedLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
113
|
+
mp = FFI::MemoryPointer.new(MixedLayout.size)
|
114
|
+
s = MixedLayout.new mp
|
115
|
+
s[:a] = 0x12345678
|
116
|
+
mp.get_int(0).should == 0x12345678
|
117
|
+
s[:b] = 0xfee1deadbeef
|
118
|
+
mp.get_int64(4).should == 0xfee1deadbeef
|
119
|
+
end
|
120
|
+
rb_maj, rb_min = RUBY_VERSION.split('.')
|
121
|
+
if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/
|
122
|
+
it "Struct#layout withs with a hash of :name => type" do
|
123
|
+
class HashLayout < FFI::Struct
|
124
|
+
layout :a => :int, :b => :long_long
|
125
|
+
end
|
126
|
+
ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
|
127
|
+
HashLayout.size.should == (ll_off + 8)
|
128
|
+
mp = FFI::MemoryPointer.new(HashLayout.size)
|
129
|
+
s = HashLayout.new mp
|
130
|
+
s[:a] = 0x12345678
|
131
|
+
mp.get_int(0).should == 0x12345678
|
132
|
+
s[:b] = 0xfee1deadbeef
|
133
|
+
mp.get_int64(ll_off).should == 0xfee1deadbeef
|
134
|
+
end
|
135
|
+
end
|
136
|
+
it "Can use Struct subclass as parameter type" do
|
137
|
+
module StructParam
|
138
|
+
extend FFI::Library
|
139
|
+
ffi_lib TestLibrary::PATH
|
140
|
+
class TestStruct < FFI::Struct
|
141
|
+
layout :c, :char
|
142
|
+
end
|
143
|
+
attach_function :struct_field_s8, [ TestStruct ], :char
|
144
|
+
end
|
145
|
+
end
|
146
|
+
it "Can use Struct subclass as IN parameter type" do
|
147
|
+
module StructParam
|
148
|
+
extend FFI::Library
|
149
|
+
ffi_lib TestLibrary::PATH
|
150
|
+
class TestStruct < FFI::Struct
|
151
|
+
layout :c, :char
|
152
|
+
end
|
153
|
+
attach_function :struct_field_s8, [ TestStruct.in ], :char
|
154
|
+
end
|
155
|
+
end
|
156
|
+
it "Can use Struct subclass as OUT parameter type" do
|
157
|
+
module StructParam
|
158
|
+
extend FFI::Library
|
159
|
+
ffi_lib TestLibrary::PATH
|
160
|
+
class TestStruct < FFI::Struct
|
161
|
+
layout :c, :char
|
162
|
+
end
|
163
|
+
attach_function :struct_field_s8, [ TestStruct.out ], :char
|
164
|
+
end
|
165
|
+
end
|
166
|
+
it "can be passed directly as a :pointer parameter" do
|
167
|
+
class TestStruct < FFI::Struct
|
168
|
+
layout :i, :int
|
169
|
+
end
|
170
|
+
s = TestStruct.new
|
171
|
+
s[:i] = 0x12
|
172
|
+
LibTest.ptr_ret_int32_t(s, 0).should == 0x12
|
173
|
+
end
|
174
|
+
it ":char member aligned correctly" do
|
175
|
+
class AlignChar < FFI::Struct
|
176
|
+
layout :c, :char, :v, :char
|
177
|
+
end
|
178
|
+
s = AlignChar.new
|
179
|
+
s[:v] = 0x12
|
180
|
+
LibTest.struct_align_s8(s.pointer).should == 0x12
|
181
|
+
end
|
182
|
+
it ":short member aligned correctly" do
|
183
|
+
class AlignShort < FFI::Struct
|
184
|
+
layout :c, :char, :v, :short
|
185
|
+
end
|
186
|
+
s = AlignShort.alloc_in
|
187
|
+
s[:v] = 0x1234
|
188
|
+
LibTest.struct_align_s16(s.pointer).should == 0x1234
|
189
|
+
end
|
190
|
+
it ":int member aligned correctly" do
|
191
|
+
class AlignInt < FFI::Struct
|
192
|
+
layout :c, :char, :v, :int
|
193
|
+
end
|
194
|
+
s = AlignInt.alloc_in
|
195
|
+
s[:v] = 0x12345678
|
196
|
+
LibTest.struct_align_s32(s.pointer).should == 0x12345678
|
197
|
+
end
|
198
|
+
it ":long_long member aligned correctly" do
|
199
|
+
class AlignLongLong < FFI::Struct
|
200
|
+
layout :c, :char, :v, :long_long
|
201
|
+
end
|
202
|
+
s = AlignLongLong.alloc_in
|
203
|
+
s[:v] = 0x123456789abcdef0
|
204
|
+
LibTest.struct_align_s64(s.pointer).should == 0x123456789abcdef0
|
205
|
+
end
|
206
|
+
it ":long member aligned correctly" do
|
207
|
+
class AlignLong < FFI::Struct
|
208
|
+
layout :c, :char, :v, :long
|
209
|
+
end
|
210
|
+
s = AlignLong.alloc_in
|
211
|
+
s[:v] = 0x12345678
|
212
|
+
LibTest.struct_align_long(s.pointer).should == 0x12345678
|
213
|
+
end
|
214
|
+
it ":float member aligned correctly" do
|
215
|
+
class AlignFloat < FFI::Struct
|
216
|
+
layout :c, :char, :v, :float
|
217
|
+
end
|
218
|
+
s = AlignFloat.alloc_in
|
219
|
+
s[:v] = 1.23456
|
220
|
+
(LibTest.struct_align_f32(s.pointer) - 1.23456).abs.should < 0.00001
|
221
|
+
end
|
222
|
+
it ":double member aligned correctly" do
|
223
|
+
class AlignDouble < FFI::Struct
|
224
|
+
layout :c, :char, :v, :double
|
225
|
+
end
|
226
|
+
s = AlignDouble.alloc_in
|
227
|
+
s[:v] = 1.23456789
|
228
|
+
(LibTest.struct_align_f64(s.pointer) - 1.23456789).abs.should < 0.00000001
|
229
|
+
end
|
230
|
+
it ":ulong, :pointer struct" do
|
231
|
+
class ULPStruct < FFI::Struct
|
232
|
+
layout :ul, :ulong, :p, :pointer
|
233
|
+
end
|
234
|
+
s = ULPStruct.alloc_in
|
235
|
+
s[:ul] = 0xdeadbeef
|
236
|
+
s[:p] = LibTest.ptr_from_address(0x12345678)
|
237
|
+
s.pointer.get_ulong(0).should == 0xdeadbeef
|
238
|
+
end
|
239
|
+
def test_num_field(type, v)
|
240
|
+
klass = Class.new(FFI::Struct)
|
241
|
+
klass.layout :v, type, :dummy, :long
|
242
|
+
|
243
|
+
s = klass.new
|
244
|
+
s[:v] = v
|
245
|
+
s.pointer.send("get_#{type.to_s}", 0).should == v
|
246
|
+
s.pointer.send("put_#{type.to_s}", 0, 0)
|
247
|
+
s[:v].should == 0
|
248
|
+
end
|
249
|
+
def self.int_field_test(type, values)
|
250
|
+
values.each do |v|
|
251
|
+
it "#{type} field r/w (#{v.to_s(16)})" do
|
252
|
+
test_num_field(type, v)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
int_field_test(:char, [ 0, 127, -128, -1 ])
|
257
|
+
int_field_test(:uchar, [ 0, 0x7f, 0x80, 0xff ])
|
258
|
+
int_field_test(:short, [ 0, 0x7fff, -0x8000, -1 ])
|
259
|
+
int_field_test(:ushort, [ 0, 0x7fff, 0x8000, 0xffff ])
|
260
|
+
int_field_test(:int, [ 0, 0x7fffffff, -0x80000000, -1 ])
|
261
|
+
int_field_test(:uint, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
|
262
|
+
int_field_test(:long_long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
|
263
|
+
int_field_test(:ulong_long, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
|
264
|
+
if FFI::Platform::LONG_SIZE == 32
|
265
|
+
int_field_test(:long, [ 0, 0x7fffffff, -0x80000000, -1 ])
|
266
|
+
int_field_test(:ulong, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
|
267
|
+
else
|
268
|
+
int_field_test(:long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
|
269
|
+
int_field_test(:ulong, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
|
270
|
+
end
|
271
|
+
it ":float field r/w" do
|
272
|
+
klass = Class.new(FFI::Struct)
|
273
|
+
klass.layout :v, :float, :dummy, :long
|
274
|
+
|
275
|
+
s = klass.new
|
276
|
+
value = 1.23456
|
277
|
+
s[:v] = value
|
278
|
+
(s.pointer.get_float(0) - value).abs.should < 0.0001
|
279
|
+
end
|
280
|
+
it ":double field r/w" do
|
281
|
+
klass = Class.new(FFI::Struct)
|
282
|
+
klass.layout :v, :double, :dummy, :long
|
283
|
+
|
284
|
+
s = klass.new
|
285
|
+
value = 1.23456
|
286
|
+
s[:v] = value
|
287
|
+
(s.pointer.get_double(0) - value).abs.should < 0.0001
|
288
|
+
end
|
289
|
+
module CallbackMember
|
290
|
+
extend FFI::Library
|
291
|
+
ffi_lib TestLibrary::PATH
|
292
|
+
callback :add, [ :int, :int ], :int
|
293
|
+
callback :sub, [ :int, :int ], :int
|
294
|
+
class TestStruct < FFI::Struct
|
295
|
+
layout :add, :add,
|
296
|
+
:sub, :sub
|
297
|
+
end
|
298
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
299
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
300
|
+
end
|
301
|
+
it "Can have CallbackInfo struct field" do
|
302
|
+
s = CallbackMember::TestStruct.new
|
303
|
+
add_proc = lambda { |a, b| a+b }
|
304
|
+
sub_proc = lambda { |a, b| a-b }
|
305
|
+
s[:add] = add_proc
|
306
|
+
s[:sub] = sub_proc
|
307
|
+
CallbackMember.struct_call_add_cb(s.pointer, 40, 2).should == 42
|
308
|
+
CallbackMember.struct_call_sub_cb(s.pointer, 44, 2).should == 42
|
309
|
+
end
|
310
|
+
it "Can return its members as a list" do
|
311
|
+
class TestStruct < FFI::Struct
|
312
|
+
layout :a, :int, :b, :int, :c, :int
|
313
|
+
end
|
314
|
+
TestStruct.members.should include(:a, :b, :c)
|
315
|
+
end
|
316
|
+
it "Can return its instance members and values as lists" do
|
317
|
+
class TestStruct < FFI::Struct
|
318
|
+
layout :a, :int, :b, :int, :c, :int
|
319
|
+
end
|
320
|
+
s = TestStruct.new
|
321
|
+
s.members.should include(:a, :b, :c)
|
322
|
+
s[:a] = 1
|
323
|
+
s[:b] = 2
|
324
|
+
s[:c] = 3
|
325
|
+
s.values.should include(1, 2, 3)
|
326
|
+
end
|
327
|
+
it 'should return an ordered field/offset pairs array' do
|
328
|
+
class TestStruct < FFI::Struct
|
329
|
+
layout :a, :int, :b, :int, :c, :int
|
330
|
+
end
|
331
|
+
s = TestStruct.new
|
332
|
+
s.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
|
333
|
+
TestStruct.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
|
334
|
+
end
|
335
|
+
it "Struct#offset_of returns offset of field within struct" do
|
336
|
+
class TestStruct < FFI::Struct
|
337
|
+
layout :a, :int, :b, :int, :c, :int
|
338
|
+
end
|
339
|
+
TestStruct.offset_of(:a).should == 0
|
340
|
+
TestStruct.offset_of(:b).should == 4
|
341
|
+
TestStruct.offset_of(:c).should == 8
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
describe FFI::Struct, ' with a nested struct field' do
|
346
|
+
module LibTest
|
347
|
+
extend FFI::Library
|
348
|
+
ffi_lib TestLibrary::PATH
|
349
|
+
class NestedStruct < FFI::Struct
|
350
|
+
layout :i, :int
|
351
|
+
end
|
352
|
+
class ContainerStruct < FFI::Struct
|
353
|
+
layout :first, :char, :ns, NestedStruct
|
354
|
+
end
|
355
|
+
attach_function :struct_align_nested_struct, [ :pointer ], :int
|
356
|
+
attach_function :struct_make_container_struct, [ :int ], :pointer
|
357
|
+
end
|
358
|
+
before do
|
359
|
+
@cs = LibTest::ContainerStruct.new
|
360
|
+
end
|
361
|
+
it 'should align correctly nested struct field' do
|
362
|
+
@cs[:ns][:i] = 123
|
363
|
+
LibTest.struct_align_nested_struct(@cs.to_ptr).should == 123
|
364
|
+
end
|
365
|
+
it 'should correctly calculate Container size (in bytes)' do
|
366
|
+
LibTest::ContainerStruct.size.should == 8
|
367
|
+
end
|
368
|
+
it 'should return a Struct object when the field is accessed' do
|
369
|
+
@cs[:ns].is_a?(FFI::Struct).should be_true
|
370
|
+
end
|
371
|
+
it 'should read a value from memory' do
|
372
|
+
@cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
|
373
|
+
@cs[:ns][:i].should == 123
|
374
|
+
end
|
375
|
+
it 'should write a value to memory' do
|
376
|
+
@cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
|
377
|
+
@cs[:ns][:i] = 456
|
378
|
+
LibTest.struct_align_nested_struct(@cs.to_ptr).should == 456
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
describe FFI::Struct, ' by value' do
|
383
|
+
module LibTest
|
384
|
+
extend FFI::Library
|
385
|
+
ffi_lib TestLibrary::PATH
|
386
|
+
|
387
|
+
class S8S32 < FFI::Struct
|
388
|
+
layout :s8, :char, :s32, :int
|
389
|
+
end
|
390
|
+
attach_function :struct_return_s8s32, [ ], S8S32.by_value
|
391
|
+
attach_function :struct_s8s32_set, [ :char, :int ], S8S32.by_value
|
392
|
+
attach_function :struct_s8s32_get_s8, [ S8S32.by_value ], :char
|
393
|
+
attach_function :struct_s8s32_get_s32, [ S8S32.by_value ], :int
|
394
|
+
attach_function :struct_s8s32_s32_ret_s32, [ S8S32.by_value, :int ], :int
|
395
|
+
attach_function :struct_s8s32_s64_ret_s64, [ S8S32.by_value, :long_long ], :long_long
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'return using pre-set values' do
|
399
|
+
s = LibTest.struct_return_s8s32
|
400
|
+
s[:s8].should == 0x7f
|
401
|
+
s[:s32].should == 0x12345678
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'return using passed in values' do
|
405
|
+
s = LibTest.struct_s8s32_set(123, 456789)
|
406
|
+
s[:s8].should == 123
|
407
|
+
s[:s32].should == 456789
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'parameter' do
|
411
|
+
s = LibTest::S8S32.new
|
412
|
+
s[:s8] = 0x12
|
413
|
+
s[:s32] = 0x34567890
|
414
|
+
LibTest.struct_s8s32_get_s8(s).should == 0x12
|
415
|
+
LibTest.struct_s8s32_get_s32(s).should == 0x34567890
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'parameter with following s32' do
|
419
|
+
s = LibTest::S8S32.new
|
420
|
+
s[:s8] = 0x12
|
421
|
+
s[:s32] = 0x34567890
|
422
|
+
|
423
|
+
LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead
|
424
|
+
end
|
425
|
+
|
426
|
+
it 'parameter with following s64' do
|
427
|
+
s = LibTest::S8S32.new
|
428
|
+
s[:s8] = 0x12
|
429
|
+
s[:s32] = 0x34567890
|
430
|
+
|
431
|
+
LibTest.struct_s8s32_s64_ret_s64(s, 0xdeadcafebabe).should == 0xdeadcafebabe
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
describe FFI::Struct, ' with an array field' do
|
436
|
+
module LibTest
|
437
|
+
extend FFI::Library
|
438
|
+
ffi_lib TestLibrary::PATH
|
439
|
+
class StructWithArray < FFI::Struct
|
440
|
+
layout :first, :char, :a, [:int, 5]
|
441
|
+
end
|
442
|
+
attach_function :struct_make_struct_with_array, [:int, :int, :int, :int, :int], :pointer
|
443
|
+
attach_function :struct_field_array, [:pointer], :pointer
|
444
|
+
end
|
445
|
+
before do
|
446
|
+
@s = LibTest::StructWithArray.new
|
447
|
+
end
|
448
|
+
it 'should correctly calculate StructWithArray size (in bytes)' do
|
449
|
+
LibTest::StructWithArray.size.should == 24
|
450
|
+
end
|
451
|
+
it 'should read values from memory' do
|
452
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
453
|
+
@s[:a].to_a.should == [0, 1, 2, 3, 4]
|
454
|
+
end
|
455
|
+
# it 'should cache array object for successive calls' do
|
456
|
+
# @s[:a].object_id.should == @s[:a].object_id
|
457
|
+
# end
|
458
|
+
it 'should return the size of the array field in bytes' do
|
459
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
460
|
+
@s[:a].size.should == 20
|
461
|
+
end
|
462
|
+
it 'should allow iteration through the array elements' do
|
463
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
464
|
+
@s[:a].each_with_index { |elem, i| elem.should == i }
|
465
|
+
end
|
466
|
+
it 'should return the pointer to the array' do
|
467
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
468
|
+
@s[:a].to_ptr.should == LibTest::struct_field_array(@s.to_ptr)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
describe 'BuggedStruct' do
|
473
|
+
module LibTest
|
474
|
+
extend FFI::Library
|
475
|
+
ffi_lib TestLibrary::PATH
|
476
|
+
class BuggedStruct < FFI::Struct
|
477
|
+
layout :visible, :uchar,
|
478
|
+
:x, :uint,
|
479
|
+
:y, :uint,
|
480
|
+
:rx, :short,
|
481
|
+
:ry, :short,
|
482
|
+
:order, :uchar,
|
483
|
+
:size, :uchar
|
484
|
+
end
|
485
|
+
attach_function :bugged_struct_size, [], :uint
|
486
|
+
end
|
487
|
+
it 'should return its correct size' do
|
488
|
+
LibTest::BuggedStruct.size.should == LibTest.bugged_struct_size
|
489
|
+
end
|
490
|
+
it "offsets within struct should be correct" do
|
491
|
+
LibTest::BuggedStruct.offset_of(:visible).should == 0
|
492
|
+
LibTest::BuggedStruct.offset_of(:x).should == 4
|
493
|
+
LibTest::BuggedStruct.offset_of(:y).should == 8
|
494
|
+
LibTest::BuggedStruct.offset_of(:rx).should == 12
|
495
|
+
LibTest::BuggedStruct.offset_of(:ry).should == 14
|
496
|
+
LibTest::BuggedStruct.offset_of(:order).should == 16
|
497
|
+
LibTest::BuggedStruct.offset_of(:size).should == 17
|
498
|
+
end
|
499
|
+
it 'should return correct field/offset pairs' do
|
500
|
+
LibTest::BuggedStruct.offsets.sort do |a, b|
|
501
|
+
a[1] <=> b[1]
|
502
|
+
end.should == [[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]]
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
describe "Struct allocation" do
|
507
|
+
it "MemoryPointer.new(Struct, 2)" do
|
508
|
+
class S < FFI::Struct
|
509
|
+
layout :i, :uint
|
510
|
+
end
|
511
|
+
p = FFI::MemoryPointer.new(S, 2)
|
512
|
+
p.total.should == 8
|
513
|
+
p.type_size.should == 4
|
514
|
+
p.put_uint(4, 0xdeadbeef)
|
515
|
+
S.new(p[1])[:i].should == 0xdeadbeef
|
516
|
+
p[1].address.should == (p[0].address + 4)
|
517
|
+
end
|
518
|
+
|
519
|
+
it "Buffer.new(Struct, 2)" do
|
520
|
+
class S < FFI::Struct
|
521
|
+
layout :i, :uint
|
522
|
+
end
|
523
|
+
p = FFI::Buffer.new(S, 2)
|
524
|
+
p.total.should == 8
|
525
|
+
p.type_size.should == 4
|
526
|
+
p.put_uint(4, 0xdeadbeef)
|
527
|
+
S.new(p[1])[:i].should == 0xdeadbeef
|
528
|
+
end
|
529
|
+
end
|