ffi 1.9.3-x64-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/COPYING +49 -0
- data/LICENSE +24 -0
- data/README.md +109 -0
- data/Rakefile +220 -0
- data/ext/ffi_c/AbstractMemory.c +1032 -0
- data/ext/ffi_c/AbstractMemory.h +175 -0
- data/ext/ffi_c/ArrayType.c +162 -0
- data/ext/ffi_c/ArrayType.h +59 -0
- data/ext/ffi_c/Buffer.c +365 -0
- data/ext/ffi_c/Call.c +465 -0
- data/ext/ffi_c/Call.h +93 -0
- data/ext/ffi_c/ClosurePool.c +283 -0
- data/ext/ffi_c/ClosurePool.h +57 -0
- data/ext/ffi_c/DataConverter.c +91 -0
- data/ext/ffi_c/DynamicLibrary.c +333 -0
- data/ext/ffi_c/DynamicLibrary.h +49 -0
- data/ext/ffi_c/Function.c +999 -0
- data/ext/ffi_c/Function.h +87 -0
- data/ext/ffi_c/FunctionInfo.c +271 -0
- data/ext/ffi_c/LastError.c +184 -0
- data/ext/ffi_c/LastError.h +47 -0
- data/ext/ffi_c/LongDouble.c +63 -0
- data/ext/ffi_c/LongDouble.h +51 -0
- data/ext/ffi_c/MappedType.c +168 -0
- data/ext/ffi_c/MappedType.h +59 -0
- data/ext/ffi_c/MemoryPointer.c +197 -0
- data/ext/ffi_c/MemoryPointer.h +53 -0
- data/ext/ffi_c/MethodHandle.c +360 -0
- data/ext/ffi_c/MethodHandle.h +55 -0
- data/ext/ffi_c/Platform.c +121 -0
- data/ext/ffi_c/Platform.h +45 -0
- data/ext/ffi_c/Pointer.c +508 -0
- data/ext/ffi_c/Pointer.h +63 -0
- data/ext/ffi_c/Struct.c +828 -0
- data/ext/ffi_c/Struct.h +106 -0
- data/ext/ffi_c/StructByReference.c +190 -0
- data/ext/ffi_c/StructByReference.h +50 -0
- data/ext/ffi_c/StructByValue.c +150 -0
- data/ext/ffi_c/StructByValue.h +55 -0
- data/ext/ffi_c/StructLayout.c +698 -0
- data/ext/ffi_c/Thread.c +352 -0
- data/ext/ffi_c/Thread.h +95 -0
- data/ext/ffi_c/Type.c +397 -0
- data/ext/ffi_c/Type.h +62 -0
- data/ext/ffi_c/Types.c +139 -0
- data/ext/ffi_c/Types.h +89 -0
- data/ext/ffi_c/Variadic.c +276 -0
- data/ext/ffi_c/compat.h +83 -0
- data/ext/ffi_c/extconf.rb +64 -0
- data/ext/ffi_c/ffi.c +98 -0
- data/ext/ffi_c/libffi.bsd.mk +34 -0
- data/ext/ffi_c/libffi.darwin.mk +95 -0
- data/ext/ffi_c/libffi.gnu.mk +31 -0
- data/ext/ffi_c/libffi.mk +13 -0
- data/ext/ffi_c/libffi.vc.mk +26 -0
- data/ext/ffi_c/libffi.vc64.mk +26 -0
- data/ext/ffi_c/libffi/ChangeLog +4600 -0
- data/ext/ffi_c/libffi/ChangeLog.libffi +584 -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 +196 -0
- data/ext/ffi_c/libffi/Makefile.in +1820 -0
- data/ext/ffi_c/libffi/Makefile.vc +141 -0
- data/ext/ffi_c/libffi/Makefile.vc64 +141 -0
- data/ext/ffi_c/libffi/README +342 -0
- data/ext/ffi_c/libffi/acinclude.m4 +92 -0
- data/ext/ffi_c/libffi/aclocal.m4 +1873 -0
- data/ext/ffi_c/libffi/build-ios.sh +67 -0
- data/ext/ffi_c/libffi/compile +143 -0
- data/ext/ffi_c/libffi/config.guess +1501 -0
- data/ext/ffi_c/libffi/config.sub +1705 -0
- data/ext/ffi_c/libffi/configure +17191 -0
- data/ext/ffi_c/libffi/configure.ac +496 -0
- data/ext/ffi_c/libffi/configure.host +11 -0
- data/ext/ffi_c/libffi/depcomp +630 -0
- data/ext/ffi_c/libffi/doc/libffi.info +593 -0
- data/ext/ffi_c/libffi/doc/libffi.texi +600 -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 +199 -0
- data/ext/ffi_c/libffi/fficonfig.hw +57 -0
- data/ext/ffi_c/libffi/include/Makefile.am +9 -0
- data/ext/ffi_c/libffi/include/Makefile.in +487 -0
- data/ext/ffi_c/libffi/include/ffi.h.in +427 -0
- 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 +126 -0
- data/ext/ffi_c/libffi/install-sh +520 -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/ltmain.sh +9636 -0
- 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 +7831 -0
- data/ext/ffi_c/libffi/m4/ltoptions.m4 +369 -0
- data/ext/ffi_c/libffi/m4/ltsugar.m4 +123 -0
- data/ext/ffi_c/libffi/m4/ltversion.m4 +23 -0
- data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +98 -0
- data/ext/ffi_c/libffi/man/Makefile.am +8 -0
- data/ext/ffi_c/libffi/man/Makefile.in +466 -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 +376 -0
- data/ext/ffi_c/libffi/msvcc.sh +197 -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 +387 -0
- data/ext/ffi_c/libffi/src/arm/ffi.c +728 -0
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +65 -0
- data/ext/ffi_c/libffi/src/arm/gentramp.sh +118 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +497 -0
- data/ext/ffi_c/libffi/src/arm/trampoline.S +4450 -0
- data/ext/ffi_c/libffi/src/avr32/ffi.c +423 -0
- data/ext/ffi_c/libffi/src/avr32/ffitarget.h +50 -0
- data/ext/ffi_c/libffi/src/avr32/sysv.S +208 -0
- data/ext/ffi_c/libffi/src/closures.c +615 -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 +5161 -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 +57 -0
- data/ext/ffi_c/libffi/src/ia64/ffi.c +582 -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 +356 -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 +288 -0
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/m68k/sysv.S +270 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +1036 -0
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +242 -0
- data/ext/ffi_c/libffi/src/mips/n32.S +591 -0
- data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
- 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 +719 -0
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +78 -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 +328 -0
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +445 -0
- data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +383 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +575 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +1448 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +1359 -0
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +139 -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 +219 -0
- data/ext/ffi_c/libffi/src/prep_cif.c +177 -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 +62 -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 +468 -0
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
- data/ext/ffi_c/libffi/src/sh64/sysv.S +539 -0
- data/ext/ffi_c/libffi/src/sparc/ffi.c +669 -0
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +68 -0
- data/ext/ffi_c/libffi/src/sparc/v8.S +313 -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 +444 -0
- data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
- data/ext/ffi_c/libffi/src/x86/ffi.c +644 -0
- data/ext/ffi_c/libffi/src/x86/ffi64.c +635 -0
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +121 -0
- data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
- data/ext/ffi_c/libffi/src/x86/sysv.S +468 -0
- data/ext/ffi_c/libffi/src/x86/unix64.S +426 -0
- data/ext/ffi_c/libffi/src/x86/win32.S +1065 -0
- data/ext/ffi_c/libffi/src/x86/win64.S +468 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.am +80 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.in +500 -0
- data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
- data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +300 -0
- data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +350 -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 +32 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +81 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +81 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +92 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_loc_fn0.c +95 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +64 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +94 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +95 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +96 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +102 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +93 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +113 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +95 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +109 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +124 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +113 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +117 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +88 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +93 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +92 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +134 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +117 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +95 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +92 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +93 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +66 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +43 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +60 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +105 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +60 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +74 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +74 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +74 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +74 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +140 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +43 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +47 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +43 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +26 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +153 -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 +58 -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/huge_struct.c +342 -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 +152 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +161 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +133 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +110 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +111 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +111 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +112 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +131 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +111 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +131 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +131 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +90 -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 +43 -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/stret_large.c +145 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +148 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +124 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +125 -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.call/testclosure.c +70 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +96 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +35 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +124 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
- data/ext/ffi_c/libffi/texinfo.tex +7210 -0
- data/ext/ffi_c/rbffi.h +57 -0
- data/ext/ffi_c/rbffi_endian.h +59 -0
- data/ext/ffi_c/win32/stdbool.h +8 -0
- data/ext/ffi_c/win32/stdint.h +201 -0
- data/ffi.gemspec +22 -0
- data/gen/Rakefile +30 -0
- data/lib/ffi.rb +28 -0
- data/lib/ffi/autopointer.rb +194 -0
- data/lib/ffi/buffer.rb +4 -0
- data/lib/ffi/callback.rb +4 -0
- data/lib/ffi/enum.rb +173 -0
- data/lib/ffi/errno.rb +43 -0
- data/lib/ffi/ffi.rb +44 -0
- data/lib/ffi/io.rb +62 -0
- data/lib/ffi/library.rb +499 -0
- data/lib/ffi/managedstruct.rb +84 -0
- data/lib/ffi/memorypointer.rb +1 -0
- data/lib/ffi/platform.rb +148 -0
- data/lib/ffi/platform/arm-linux/types.conf +104 -0
- data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
- data/lib/ffi/platform/i386-darwin/types.conf +100 -0
- data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
- data/lib/ffi/platform/i386-gnu/types.conf +107 -0
- data/lib/ffi/platform/i386-linux/types.conf +103 -0
- data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
- data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
- data/lib/ffi/platform/i386-solaris/types.conf +122 -0
- data/lib/ffi/platform/i386-windows/types.conf +105 -0
- data/lib/ffi/platform/ia64-linux/types.conf +104 -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-aix/types.conf +180 -0
- data/lib/ffi/platform/powerpc-darwin/types.conf +100 -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/sparc-solaris/types.conf +128 -0
- data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
- data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
- data/lib/ffi/platform/x86_64-darwin/types.conf +100 -0
- data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
- data/lib/ffi/platform/x86_64-linux/types.conf +102 -0
- data/lib/ffi/platform/x86_64-netbsd/types.conf +126 -0
- data/lib/ffi/platform/x86_64-openbsd/types.conf +128 -0
- data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
- data/lib/ffi/platform/x86_64-windows/types.conf +27 -0
- data/lib/ffi/pointer.rb +134 -0
- data/lib/ffi/struct.rb +367 -0
- data/lib/ffi/struct_layout_builder.rb +222 -0
- data/lib/ffi/tools/const_generator.rb +229 -0
- data/lib/ffi/tools/generator.rb +60 -0
- data/lib/ffi/tools/generator_task.rb +36 -0
- data/lib/ffi/tools/struct_generator.rb +194 -0
- data/lib/ffi/tools/types_generator.rb +135 -0
- data/lib/ffi/types.rb +190 -0
- data/lib/ffi/union.rb +43 -0
- data/lib/ffi/variadic.rb +78 -0
- data/lib/ffi/version.rb +4 -0
- data/lib/ffi_c.so +0 -0
- data/libtest/Benchmark.c +52 -0
- data/libtest/BoolTest.c +34 -0
- data/libtest/BufferTest.c +31 -0
- data/libtest/ClosureTest.c +190 -0
- data/libtest/EnumTest.c +34 -0
- data/libtest/FunctionTest.c +58 -0
- data/libtest/GNUmakefile +149 -0
- data/libtest/GlobalVariable.c +62 -0
- data/libtest/LastErrorTest.c +21 -0
- data/libtest/NumberTest.c +132 -0
- data/libtest/PointerTest.c +63 -0
- data/libtest/ReferenceTest.c +23 -0
- data/libtest/StringTest.c +34 -0
- data/libtest/StructTest.c +243 -0
- data/libtest/UnionTest.c +43 -0
- data/libtest/VariadicTest.c +62 -0
- data/spec/ffi/async_callback_spec.rb +35 -0
- data/spec/ffi/bool_spec.rb +29 -0
- data/spec/ffi/buffer_spec.rb +251 -0
- data/spec/ffi/callback_spec.rb +667 -0
- data/spec/ffi/custom_param_type.rb +36 -0
- data/spec/ffi/custom_type_spec.rb +74 -0
- data/spec/ffi/dup_spec.rb +54 -0
- data/spec/ffi/enum_spec.rb +220 -0
- data/spec/ffi/errno_spec.rb +18 -0
- data/spec/ffi/ffi_spec.rb +29 -0
- data/spec/ffi/function_spec.rb +76 -0
- data/spec/ffi/library_spec.rb +216 -0
- data/spec/ffi/long_double.rb +30 -0
- data/spec/ffi/managed_struct_spec.rb +57 -0
- data/spec/ffi/number_spec.rb +236 -0
- data/spec/ffi/pointer_spec.rb +265 -0
- data/spec/ffi/rbx/attach_function_spec.rb +28 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +123 -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 +33 -0
- data/spec/ffi/string_spec.rb +108 -0
- data/spec/ffi/strptr_spec.rb +50 -0
- data/spec/ffi/struct_by_ref_spec.rb +43 -0
- data/spec/ffi/struct_callback_spec.rb +69 -0
- data/spec/ffi/struct_initialize_spec.rb +35 -0
- data/spec/ffi/struct_packed_spec.rb +51 -0
- data/spec/ffi/struct_spec.rb +748 -0
- data/spec/ffi/typedef_spec.rb +78 -0
- data/spec/ffi/union_spec.rb +65 -0
- data/spec/ffi/variadic_spec.rb +92 -0
- data/spec/spec.opts +4 -0
- metadata +562 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of ruby-ffi.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
4
|
+
#
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
7
|
+
describe "String tests" do
|
8
|
+
include FFI
|
9
|
+
module StrLibTest
|
10
|
+
extend FFI::Library
|
11
|
+
ffi_lib TestLibrary::PATH
|
12
|
+
attach_function :ptr_ret_pointer, [ :pointer, :int], :string
|
13
|
+
attach_function :string_equals, [ :string, :string ], :int
|
14
|
+
attach_function :string_dummy, [ :string ], :void
|
15
|
+
attach_function :string_null, [ ], :string
|
16
|
+
end
|
17
|
+
it "MemoryPointer#get_string returns a tainted string" do
|
18
|
+
mp = FFI::MemoryPointer.new 1024
|
19
|
+
mp.put_string(0, "test\0")
|
20
|
+
str = mp.get_string(0)
|
21
|
+
str.tainted?.should == true
|
22
|
+
end
|
23
|
+
it "String returned by a method is tainted" do
|
24
|
+
mp = FFI::MemoryPointer.new :pointer
|
25
|
+
sp = FFI::MemoryPointer.new 1024
|
26
|
+
sp.put_string(0, "test")
|
27
|
+
mp.put_pointer(0, sp)
|
28
|
+
str = StrLibTest.ptr_ret_pointer(mp, 0)
|
29
|
+
str.should == "test"
|
30
|
+
str.tainted?.should == true
|
31
|
+
end
|
32
|
+
it "Poison null byte raises error" do
|
33
|
+
s = "123\0abc"
|
34
|
+
lambda { StrLibTest.string_equals(s, s) }.should raise_error
|
35
|
+
end
|
36
|
+
it "Tainted String parameter should throw a SecurityError" do
|
37
|
+
$SAFE = 1
|
38
|
+
str = "test"
|
39
|
+
str.taint
|
40
|
+
begin
|
41
|
+
LibTest.string_equals(str, str).should == false
|
42
|
+
rescue SecurityError
|
43
|
+
end
|
44
|
+
end if false
|
45
|
+
it "casts nil as NULL pointer" do
|
46
|
+
StrLibTest.string_dummy(nil)
|
47
|
+
end
|
48
|
+
it "return nil for NULL char*" do
|
49
|
+
StrLibTest.string_null.should == nil
|
50
|
+
end
|
51
|
+
it "reads an array of strings until encountering a NULL pointer" do
|
52
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
53
|
+
ptrary = FFI::MemoryPointer.new(:pointer, 6)
|
54
|
+
ary = strings.inject([]) do |a, str|
|
55
|
+
f = FFI::MemoryPointer.new(1024)
|
56
|
+
f.put_string(0, str)
|
57
|
+
a << f
|
58
|
+
end
|
59
|
+
ary.insert(3, nil)
|
60
|
+
ptrary.write_array_of_pointer(ary)
|
61
|
+
ptrary.get_array_of_string(0).should == ["foo", "bar", "baz"]
|
62
|
+
end
|
63
|
+
it "reads an array of strings of the size specified, substituting nil when a pointer is NULL" do
|
64
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
65
|
+
ptrary = FFI::MemoryPointer.new(:pointer, 6)
|
66
|
+
ary = strings.inject([]) do |a, str|
|
67
|
+
f = FFI::MemoryPointer.new(1024)
|
68
|
+
f.put_string(0, str)
|
69
|
+
a << f
|
70
|
+
end
|
71
|
+
ary.insert(2, nil)
|
72
|
+
ptrary.write_array_of_pointer(ary)
|
73
|
+
ptrary.get_array_of_string(0, 4).should == ["foo", "bar", nil, "baz"]
|
74
|
+
end
|
75
|
+
it "reads an array of strings, taking a memory offset parameter" do
|
76
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
77
|
+
ptrary = FFI::MemoryPointer.new(:pointer, 5)
|
78
|
+
ary = strings.inject([]) do |a, str|
|
79
|
+
f = FFI::MemoryPointer.new(1024)
|
80
|
+
f.put_string(0, str)
|
81
|
+
a << f
|
82
|
+
end
|
83
|
+
ptrary.write_array_of_pointer(ary)
|
84
|
+
ptrary.get_array_of_string(2 * FFI.type_size(:pointer), 3).should == ["baz", "testing", "ffi"]
|
85
|
+
end
|
86
|
+
it "raises an IndexError when trying to read an array of strings out of bounds" do
|
87
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
88
|
+
ptrary = FFI::MemoryPointer.new(:pointer, 5)
|
89
|
+
ary = strings.inject([]) do |a, str|
|
90
|
+
f = FFI::MemoryPointer.new(1024)
|
91
|
+
f.put_string(0, str)
|
92
|
+
a << f
|
93
|
+
end
|
94
|
+
ptrary.write_array_of_pointer(ary)
|
95
|
+
lambda { ptrary.get_array_of_string(0, 6) }.should raise_error
|
96
|
+
end
|
97
|
+
it "raises an IndexError when trying to read an array of strings using a negative offset" do
|
98
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
99
|
+
ptrary = FFI::MemoryPointer.new(:pointer, 5)
|
100
|
+
ary = strings.inject([]) do |a, str|
|
101
|
+
f = FFI::MemoryPointer.new(1024)
|
102
|
+
f.put_string(0, str)
|
103
|
+
a << f
|
104
|
+
end
|
105
|
+
ptrary.write_array_of_pointer(ary)
|
106
|
+
lambda { ptrary.get_array_of_string(-1) }.should raise_error
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of ruby-ffi.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
4
|
+
#
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
7
|
+
|
8
|
+
describe "functions returning :strptr" do
|
9
|
+
|
10
|
+
it "can attach function with :strptr return type" do
|
11
|
+
lambda do
|
12
|
+
Module.new do
|
13
|
+
extend FFI::Library
|
14
|
+
ffi_lib FFI::Library::LIBC
|
15
|
+
if !FFI::Platform.windows?
|
16
|
+
attach_function :strdup, [ :string ], :strptr
|
17
|
+
else
|
18
|
+
attach_function :_strdup, [ :string ], :strptr
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end.should_not raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
module StrPtr
|
25
|
+
extend FFI::Library
|
26
|
+
ffi_lib FFI::Library::LIBC
|
27
|
+
attach_function :free, [ :pointer ], :void
|
28
|
+
if !FFI::Platform.windows?
|
29
|
+
attach_function :strdup, [ :string ], :strptr
|
30
|
+
else
|
31
|
+
attach_function :strdup, :_strdup, [ :string ], :strptr
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return [ String, Pointer ]" do
|
36
|
+
result = StrPtr.strdup("test")
|
37
|
+
result[0].is_a?(String).should be_true
|
38
|
+
result[1].is_a?(FFI::Pointer).should be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return the correct value" do
|
42
|
+
result = StrPtr.strdup("test")
|
43
|
+
result[0].should == "test"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return non-NULL pointer" do
|
47
|
+
result = StrPtr.strdup("test")
|
48
|
+
result[1].null?.should be_false
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of ruby-ffi.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
4
|
+
#
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
7
|
+
|
8
|
+
describe FFI::Struct, ' by_ref' do
|
9
|
+
before :all do
|
10
|
+
@struct_class = struct_class = Class.new(FFI::Struct) do
|
11
|
+
layout :a, :pointer
|
12
|
+
end
|
13
|
+
|
14
|
+
@api = Module.new do
|
15
|
+
extend FFI::Library
|
16
|
+
ffi_lib TestLibrary::PATH
|
17
|
+
fn = FFI::Type::POINTER.size == FFI::Type::LONG.size ? :ret_ulong : ret_uint64_t
|
18
|
+
attach_function :struct_test, fn, [ struct_class.by_ref ], :pointer
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should accept instances of exact struct class" do
|
23
|
+
s = @struct_class.new
|
24
|
+
@api.struct_test(s).should == s.pointer
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should accept nil" do
|
28
|
+
@api.struct_test(nil).should == nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should reject other types" do
|
32
|
+
lambda { @api.struct_test('test').should == nil }.should raise_error(TypeError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should reject instances of other struct classes" do
|
36
|
+
other_class = Class.new(FFI::Struct) do
|
37
|
+
layout :a, :pointer
|
38
|
+
end
|
39
|
+
|
40
|
+
lambda { @api.struct_test(other_class.new) }.should raise_error(TypeError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of ruby-ffi.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
4
|
+
#
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
7
|
+
|
8
|
+
describe FFI::Struct, ' with inline callback functions' do
|
9
|
+
it 'should be able to define inline callback field' do
|
10
|
+
module CallbackMember1
|
11
|
+
extend FFI::Library
|
12
|
+
ffi_lib TestLibrary::PATH
|
13
|
+
DUMMY_CB = callback :dummy_cb, [ :int ], :int
|
14
|
+
class TestStruct < FFI::Struct
|
15
|
+
layout \
|
16
|
+
:add, callback([ :int, :int ], :int),
|
17
|
+
:sub, callback([ :int, :int ], :int),
|
18
|
+
:cb_with_cb_parameter, callback([ DUMMY_CB, :int ], :int)
|
19
|
+
end
|
20
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
21
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
22
|
+
end
|
23
|
+
end
|
24
|
+
it 'should take methods as callbacks' do
|
25
|
+
module CallbackMember2
|
26
|
+
extend FFI::Library
|
27
|
+
ffi_lib TestLibrary::PATH
|
28
|
+
class TestStruct < FFI::Struct
|
29
|
+
layout \
|
30
|
+
:add, callback([ :int, :int ], :int),
|
31
|
+
:sub, callback([ :int, :int ], :int)
|
32
|
+
end
|
33
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
34
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
35
|
+
end
|
36
|
+
module StructCallbacks
|
37
|
+
def self.add a, b
|
38
|
+
a+b
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
ts = CallbackMember2::TestStruct.new
|
43
|
+
ts[:add] = StructCallbacks.method(:add)
|
44
|
+
|
45
|
+
CallbackMember2.struct_call_add_cb(ts, 1, 2).should == 3
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should return callable object from []' do
|
49
|
+
module CallbackMember3
|
50
|
+
extend FFI::Library
|
51
|
+
ffi_lib TestLibrary::PATH
|
52
|
+
class TestStruct < FFI::Struct
|
53
|
+
layout \
|
54
|
+
:add, callback([ :int, :int ], :int),
|
55
|
+
:sub, callback([ :int, :int ], :int)
|
56
|
+
end
|
57
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
58
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
59
|
+
end
|
60
|
+
|
61
|
+
s = CallbackMember3::TestStruct.new
|
62
|
+
add = Proc.new { |a,b| a+b}
|
63
|
+
s[:add] = add
|
64
|
+
fn = s[:add]
|
65
|
+
fn.respond_to?(:call).should be_true
|
66
|
+
fn.call(1, 2).should == 3
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of ruby-ffi.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
4
|
+
#
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
7
|
+
|
8
|
+
describe FFI::Struct, ' with an initialize function' do
|
9
|
+
it "should call the initialize function" do
|
10
|
+
class StructWithInitialize < FFI::Struct
|
11
|
+
layout :string, :string
|
12
|
+
attr_accessor :magic
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
self.magic = 42
|
16
|
+
end
|
17
|
+
end
|
18
|
+
StructWithInitialize.new.magic.should == 42
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe FFI::ManagedStruct, ' with an initialize function' do
|
23
|
+
it "should call the initialize function" do
|
24
|
+
class ManagedStructWithInitialize < FFI::ManagedStruct
|
25
|
+
layout :string, :string
|
26
|
+
attr_accessor :magic
|
27
|
+
def initialize
|
28
|
+
super FFI::MemoryPointer.new(:pointer).put_int(0, 0x1234).get_pointer(0)
|
29
|
+
self.magic = 42
|
30
|
+
end
|
31
|
+
def self.release;end
|
32
|
+
end
|
33
|
+
ManagedStructWithInitialize.new.magic.should == 42
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of ruby-ffi.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
4
|
+
#
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
7
|
+
|
8
|
+
describe FFI::Struct do
|
9
|
+
it "packed :char followed by :int should have size of 5" do
|
10
|
+
Class.new(FFI::Struct) do
|
11
|
+
packed
|
12
|
+
layout :c, :char, :i, :int
|
13
|
+
end.size.should == 5
|
14
|
+
end
|
15
|
+
|
16
|
+
it "packed :char followed by :int should have alignment of 1" do
|
17
|
+
Class.new(FFI::Struct) do
|
18
|
+
packed
|
19
|
+
layout :c, :char, :i, :int
|
20
|
+
end.alignment.should == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "packed(2) :char followed by :int should have size of 6" do
|
24
|
+
Class.new(FFI::Struct) do
|
25
|
+
packed 2
|
26
|
+
layout :c, :char, :i, :int
|
27
|
+
end.size.should == 6
|
28
|
+
end
|
29
|
+
|
30
|
+
it "packed(2) :char followed by :int should have alignment of 2" do
|
31
|
+
Class.new(FFI::Struct) do
|
32
|
+
packed 2
|
33
|
+
layout :c, :char, :i, :int
|
34
|
+
end.alignment.should == 2
|
35
|
+
end
|
36
|
+
|
37
|
+
it "packed :short followed by int should have size of 6" do
|
38
|
+
Class.new(FFI::Struct) do
|
39
|
+
packed
|
40
|
+
layout :s, :short, :i, :int
|
41
|
+
end.size.should == 6
|
42
|
+
end
|
43
|
+
|
44
|
+
it "packed :short followed by int should have alignment of 1" do
|
45
|
+
Class.new(FFI::Struct) do
|
46
|
+
packed
|
47
|
+
layout :s, :short, :i, :int
|
48
|
+
end.alignment.should == 1
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,748 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of ruby-ffi.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
4
|
+
#
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
7
|
+
describe "Struct tests" do
|
8
|
+
StructTypes = {
|
9
|
+
's8' => :char,
|
10
|
+
's16' => :short,
|
11
|
+
's32' => :int,
|
12
|
+
's64' => :long_long,
|
13
|
+
'long' => :long,
|
14
|
+
'f32' => :float,
|
15
|
+
'f64' => :double
|
16
|
+
}
|
17
|
+
module LibTest
|
18
|
+
extend FFI::Library
|
19
|
+
ffi_lib TestLibrary::PATH
|
20
|
+
attach_function :ptr_ret_pointer, [ :pointer, :int], :string
|
21
|
+
attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
|
22
|
+
attach_function :ptr_from_address, [ :ulong ], :pointer
|
23
|
+
attach_function :string_equals, [ :string, :string ], :int
|
24
|
+
[ 's8', 's16', 's32', 's64', 'f32', 'f64', 'long' ].each do |t|
|
25
|
+
attach_function "struct_align_#{t}", [ :pointer ], StructTypes[t]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
class PointerMember < FFI::Struct
|
29
|
+
layout :pointer, :pointer
|
30
|
+
end
|
31
|
+
class StringMember < FFI::Struct
|
32
|
+
layout :string, :string
|
33
|
+
end
|
34
|
+
it "Struct#[:pointer]" do
|
35
|
+
magic = 0x12345678
|
36
|
+
mp = FFI::MemoryPointer.new :long
|
37
|
+
mp.put_long(0, magic)
|
38
|
+
smp = FFI::MemoryPointer.new :pointer
|
39
|
+
smp.put_pointer(0, mp)
|
40
|
+
s = PointerMember.new smp
|
41
|
+
s[:pointer].should == mp
|
42
|
+
end
|
43
|
+
it "Struct#[:pointer].nil? for NULL value" do
|
44
|
+
magic = 0x12345678
|
45
|
+
mp = FFI::MemoryPointer.new :long
|
46
|
+
mp.put_long(0, magic)
|
47
|
+
smp = FFI::MemoryPointer.new :pointer
|
48
|
+
smp.put_pointer(0, nil)
|
49
|
+
s = PointerMember.new smp
|
50
|
+
s[:pointer].null?.should == true
|
51
|
+
end
|
52
|
+
it "Struct#[:pointer]=" do
|
53
|
+
magic = 0x12345678
|
54
|
+
mp = FFI::MemoryPointer.new :long
|
55
|
+
mp.put_long(0, magic)
|
56
|
+
smp = FFI::MemoryPointer.new :pointer
|
57
|
+
s = PointerMember.new smp
|
58
|
+
s[:pointer] = mp
|
59
|
+
smp.get_pointer(0).should == mp
|
60
|
+
end
|
61
|
+
it "Struct#[:pointer]=struct" do
|
62
|
+
smp = FFI::MemoryPointer.new :pointer
|
63
|
+
s = PointerMember.new smp
|
64
|
+
lambda { s[:pointer] = s }.should_not raise_error
|
65
|
+
end
|
66
|
+
it "Struct#[:pointer]=nil" do
|
67
|
+
smp = FFI::MemoryPointer.new :pointer
|
68
|
+
s = PointerMember.new smp
|
69
|
+
s[:pointer] = nil
|
70
|
+
smp.get_pointer(0).null?.should == true
|
71
|
+
end
|
72
|
+
it "Struct#[:string]" do
|
73
|
+
magic = "test"
|
74
|
+
mp = FFI::MemoryPointer.new 1024
|
75
|
+
mp.put_string(0, magic)
|
76
|
+
smp = FFI::MemoryPointer.new :pointer
|
77
|
+
smp.put_pointer(0, mp)
|
78
|
+
s = StringMember.new smp
|
79
|
+
s[:string].should == magic
|
80
|
+
end
|
81
|
+
it "Struct#[:string].nil? for NULL value" do
|
82
|
+
smp = FFI::MemoryPointer.new :pointer
|
83
|
+
smp.put_pointer(0, nil)
|
84
|
+
s = StringMember.new smp
|
85
|
+
s[:string].nil?.should == true
|
86
|
+
end
|
87
|
+
it "Struct#layout works with :name, :type pairs" do
|
88
|
+
class PairLayout < FFI::Struct
|
89
|
+
layout :a, :int, :b, :long_long
|
90
|
+
end
|
91
|
+
ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8)
|
92
|
+
PairLayout.size.should == (ll_off + 8)
|
93
|
+
mp = FFI::MemoryPointer.new(PairLayout.size)
|
94
|
+
s = PairLayout.new mp
|
95
|
+
s[:a] = 0x12345678
|
96
|
+
mp.get_int(0).should == 0x12345678
|
97
|
+
s[:b] = 0xfee1deadbeef
|
98
|
+
mp.get_int64(ll_off).should == 0xfee1deadbeef
|
99
|
+
end
|
100
|
+
it "Struct#layout works with :name, :type, offset tuples" do
|
101
|
+
class PairLayout < FFI::Struct
|
102
|
+
layout :a, :int, 0, :b, :long_long, 4
|
103
|
+
end
|
104
|
+
PairLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
105
|
+
mp = FFI::MemoryPointer.new(PairLayout.size)
|
106
|
+
s = PairLayout.new mp
|
107
|
+
s[:a] = 0x12345678
|
108
|
+
mp.get_int(0).should == 0x12345678
|
109
|
+
s[:b] = 0xfee1deadbeef
|
110
|
+
mp.get_int64(4).should == 0xfee1deadbeef
|
111
|
+
end
|
112
|
+
it "Struct#layout works with mixed :name,:type and :name,:type,offset" do
|
113
|
+
class MixedLayout < FFI::Struct
|
114
|
+
layout :a, :int, :b, :long_long, 4
|
115
|
+
end
|
116
|
+
MixedLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
117
|
+
mp = FFI::MemoryPointer.new(MixedLayout.size)
|
118
|
+
s = MixedLayout.new mp
|
119
|
+
s[:a] = 0x12345678
|
120
|
+
mp.get_int(0).should == 0x12345678
|
121
|
+
s[:b] = 0xfee1deadbeef
|
122
|
+
mp.get_int64(4).should == 0xfee1deadbeef
|
123
|
+
end
|
124
|
+
rb_maj, rb_min = RUBY_VERSION.split('.')
|
125
|
+
if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/
|
126
|
+
it "Struct#layout withs with a hash of :name => type" do
|
127
|
+
class HashLayout < FFI::Struct
|
128
|
+
layout :a => :int, :b => :long_long
|
129
|
+
end
|
130
|
+
ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
|
131
|
+
HashLayout.size.should == (ll_off + 8)
|
132
|
+
mp = FFI::MemoryPointer.new(HashLayout.size)
|
133
|
+
s = HashLayout.new mp
|
134
|
+
s[:a] = 0x12345678
|
135
|
+
mp.get_int(0).should == 0x12345678
|
136
|
+
s[:b] = 0xfee1deadbeef
|
137
|
+
mp.get_int64(ll_off).should == 0xfee1deadbeef
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it "subclass overrides initialize without calling super" do
|
142
|
+
class InitializeWithoutSuper < FFI::Struct
|
143
|
+
layout :a, :int, :b, :long_long, :d, [:double, 2]
|
144
|
+
|
145
|
+
def initialize(a, b)
|
146
|
+
self[:a] = a
|
147
|
+
self[:b] = b
|
148
|
+
self[:d][0] = 1.2
|
149
|
+
self[:d][1] = 3.4
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
s = InitializeWithoutSuper.new(0x1eefbeef, 0xdeadcafebabe)
|
154
|
+
s[:a].should == 0x1eefbeef
|
155
|
+
s[:b].should == 0xdeadcafebabe
|
156
|
+
end
|
157
|
+
|
158
|
+
it "Can use Struct subclass as parameter type" do
|
159
|
+
module StructParam
|
160
|
+
extend FFI::Library
|
161
|
+
ffi_lib TestLibrary::PATH
|
162
|
+
class TestStruct < FFI::Struct
|
163
|
+
layout :c, :char
|
164
|
+
end
|
165
|
+
attach_function :struct_field_s8, [ TestStruct.in ], :char
|
166
|
+
end
|
167
|
+
end
|
168
|
+
it "Can use Struct subclass as IN parameter type" do
|
169
|
+
module StructParam2
|
170
|
+
extend FFI::Library
|
171
|
+
ffi_lib TestLibrary::PATH
|
172
|
+
class TestStruct < FFI::Struct
|
173
|
+
layout :c, :char
|
174
|
+
end
|
175
|
+
attach_function :struct_field_s8, [ TestStruct.in ], :char
|
176
|
+
end
|
177
|
+
end
|
178
|
+
it "Can use Struct subclass as OUT parameter type" do
|
179
|
+
module StructParam3
|
180
|
+
extend FFI::Library
|
181
|
+
ffi_lib TestLibrary::PATH
|
182
|
+
class TestStruct < FFI::Struct
|
183
|
+
layout :c, :char
|
184
|
+
end
|
185
|
+
attach_function :struct_field_s8, [ TestStruct.out ], :char
|
186
|
+
end
|
187
|
+
end
|
188
|
+
it "can be passed directly as a :pointer parameter" do
|
189
|
+
class TestStruct < FFI::Struct
|
190
|
+
layout :i, :int
|
191
|
+
end
|
192
|
+
s = TestStruct.new
|
193
|
+
s[:i] = 0x12
|
194
|
+
LibTest.ptr_ret_int32_t(s, 0).should == 0x12
|
195
|
+
end
|
196
|
+
it ":char member aligned correctly" do
|
197
|
+
class AlignChar < FFI::Struct
|
198
|
+
layout :c, :char, :v, :char
|
199
|
+
end
|
200
|
+
s = AlignChar.new
|
201
|
+
s[:v] = 0x12
|
202
|
+
LibTest.struct_align_s8(s.pointer).should == 0x12
|
203
|
+
end
|
204
|
+
it ":short member aligned correctly" do
|
205
|
+
class AlignShort < FFI::Struct
|
206
|
+
layout :c, :char, :v, :short
|
207
|
+
end
|
208
|
+
s = AlignShort.alloc_in
|
209
|
+
s[:v] = 0x1234
|
210
|
+
LibTest.struct_align_s16(s.pointer).should == 0x1234
|
211
|
+
end
|
212
|
+
it ":int member aligned correctly" do
|
213
|
+
class AlignInt < FFI::Struct
|
214
|
+
layout :c, :char, :v, :int
|
215
|
+
end
|
216
|
+
s = AlignInt.alloc_in
|
217
|
+
s[:v] = 0x12345678
|
218
|
+
LibTest.struct_align_s32(s.pointer).should == 0x12345678
|
219
|
+
end
|
220
|
+
it ":long_long member aligned correctly" do
|
221
|
+
class AlignLongLong < FFI::Struct
|
222
|
+
layout :c, :char, :v, :long_long
|
223
|
+
end
|
224
|
+
s = AlignLongLong.alloc_in
|
225
|
+
s[:v] = 0x123456789abcdef0
|
226
|
+
LibTest.struct_align_s64(s.pointer).should == 0x123456789abcdef0
|
227
|
+
end
|
228
|
+
it ":long member aligned correctly" do
|
229
|
+
class AlignLong < FFI::Struct
|
230
|
+
layout :c, :char, :v, :long
|
231
|
+
end
|
232
|
+
s = AlignLong.alloc_in
|
233
|
+
s[:v] = 0x12345678
|
234
|
+
LibTest.struct_align_long(s.pointer).should == 0x12345678
|
235
|
+
end
|
236
|
+
it ":float member aligned correctly" do
|
237
|
+
class AlignFloat < FFI::Struct
|
238
|
+
layout :c, :char, :v, :float
|
239
|
+
end
|
240
|
+
s = AlignFloat.alloc_in
|
241
|
+
s[:v] = 1.23456
|
242
|
+
(LibTest.struct_align_f32(s.pointer) - 1.23456).abs.should < 0.00001
|
243
|
+
end
|
244
|
+
it ":double member aligned correctly" do
|
245
|
+
class AlignDouble < FFI::Struct
|
246
|
+
layout :c, :char, :v, :double
|
247
|
+
end
|
248
|
+
s = AlignDouble.alloc_in
|
249
|
+
s[:v] = 1.23456789
|
250
|
+
(LibTest.struct_align_f64(s.pointer) - 1.23456789).abs.should < 0.00000001
|
251
|
+
end
|
252
|
+
it ":ulong, :pointer struct" do
|
253
|
+
class ULPStruct < FFI::Struct
|
254
|
+
layout :ul, :ulong, :p, :pointer
|
255
|
+
end
|
256
|
+
s = ULPStruct.alloc_in
|
257
|
+
s[:ul] = 0xdeadbeef
|
258
|
+
s[:p] = LibTest.ptr_from_address(0x12345678)
|
259
|
+
s.pointer.get_ulong(0).should == 0xdeadbeef
|
260
|
+
end
|
261
|
+
def test_num_field(type, v)
|
262
|
+
klass = Class.new(FFI::Struct)
|
263
|
+
klass.layout :v, type, :dummy, :long
|
264
|
+
|
265
|
+
s = klass.new
|
266
|
+
s[:v] = v
|
267
|
+
s.pointer.send("get_#{type.to_s}", 0).should == v
|
268
|
+
s.pointer.send("put_#{type.to_s}", 0, 0)
|
269
|
+
s[:v].should == 0
|
270
|
+
end
|
271
|
+
def self.int_field_test(type, values)
|
272
|
+
values.each do |v|
|
273
|
+
it "#{type} field r/w (#{v.to_s(16)})" do
|
274
|
+
test_num_field(type, v)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
int_field_test(:char, [ 0, 127, -128, -1 ])
|
279
|
+
int_field_test(:uchar, [ 0, 0x7f, 0x80, 0xff ])
|
280
|
+
int_field_test(:short, [ 0, 0x7fff, -0x8000, -1 ])
|
281
|
+
int_field_test(:ushort, [ 0, 0x7fff, 0x8000, 0xffff ])
|
282
|
+
int_field_test(:int, [ 0, 0x7fffffff, -0x80000000, -1 ])
|
283
|
+
int_field_test(:uint, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
|
284
|
+
int_field_test(:long_long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
|
285
|
+
int_field_test(:ulong_long, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
|
286
|
+
if FFI::Platform::LONG_SIZE == 32
|
287
|
+
int_field_test(:long, [ 0, 0x7fffffff, -0x80000000, -1 ])
|
288
|
+
int_field_test(:ulong, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
|
289
|
+
else
|
290
|
+
int_field_test(:long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
|
291
|
+
int_field_test(:ulong, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
|
292
|
+
end
|
293
|
+
it ":float field r/w" do
|
294
|
+
klass = Class.new(FFI::Struct)
|
295
|
+
klass.layout :v, :float, :dummy, :long
|
296
|
+
|
297
|
+
s = klass.new
|
298
|
+
value = 1.23456
|
299
|
+
s[:v] = value
|
300
|
+
(s.pointer.get_float(0) - value).abs.should < 0.0001
|
301
|
+
end
|
302
|
+
it ":double field r/w" do
|
303
|
+
klass = Class.new(FFI::Struct)
|
304
|
+
klass.layout :v, :double, :dummy, :long
|
305
|
+
|
306
|
+
s = klass.new
|
307
|
+
value = 1.23456
|
308
|
+
s[:v] = value
|
309
|
+
(s.pointer.get_double(0) - value).abs.should < 0.0001
|
310
|
+
end
|
311
|
+
module EnumFields
|
312
|
+
extend FFI::Library
|
313
|
+
TestEnum = enum :test_enum, [:c1, 10, :c2, 20, :c3, 30, :c4, 40]
|
314
|
+
class TestStruct < FFI::Struct
|
315
|
+
layout :a, :int, :c, :test_enum,
|
316
|
+
:d, [ TestEnum, TestEnum.symbols.length ]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
it ":enum field r/w" do
|
321
|
+
s = EnumFields::TestStruct.new
|
322
|
+
s[:c] = :c3
|
323
|
+
|
324
|
+
s.pointer.get_uint(FFI::Type::INT32.size).should == 30
|
325
|
+
s[:c].should == :c3
|
326
|
+
end
|
327
|
+
|
328
|
+
it "array of :enum field" do
|
329
|
+
s = EnumFields::TestStruct.new
|
330
|
+
EnumFields::TestEnum.symbols.each_with_index do |val, i|
|
331
|
+
s[:d][i] = val
|
332
|
+
end
|
333
|
+
|
334
|
+
EnumFields::TestEnum.symbols.each_with_index do |val, i|
|
335
|
+
s.pointer.get_uint(FFI::Type::INT32.size * (2 + i)).should == EnumFields::TestEnum[val]
|
336
|
+
end
|
337
|
+
|
338
|
+
s[:d].each_with_index do |val, i|
|
339
|
+
val.should == EnumFields::TestEnum.symbols[i]
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
module CallbackMember
|
344
|
+
extend FFI::Library
|
345
|
+
ffi_lib TestLibrary::PATH
|
346
|
+
callback :add, [ :int, :int ], :int
|
347
|
+
callback :sub, [ :int, :int ], :int
|
348
|
+
class TestStruct < FFI::Struct
|
349
|
+
layout :add, :add,
|
350
|
+
:sub, :sub
|
351
|
+
end
|
352
|
+
attach_function :struct_call_add_cb, [TestStruct.in, :int, :int], :int
|
353
|
+
attach_function :struct_call_sub_cb, [TestStruct.in, :int, :int], :int
|
354
|
+
end
|
355
|
+
it "Can have CallbackInfo struct field" do
|
356
|
+
s = CallbackMember::TestStruct.new
|
357
|
+
add_proc = lambda { |a, b| a+b }
|
358
|
+
sub_proc = lambda { |a, b| a-b }
|
359
|
+
s[:add] = add_proc
|
360
|
+
s[:sub] = sub_proc
|
361
|
+
CallbackMember.struct_call_add_cb(s, 40, 2).should == 42
|
362
|
+
CallbackMember.struct_call_sub_cb(s, 44, 2).should == 42
|
363
|
+
end
|
364
|
+
it "Can return its members as a list" do
|
365
|
+
class TestStruct < FFI::Struct
|
366
|
+
layout :a, :int, :b, :int, :c, :int
|
367
|
+
end
|
368
|
+
TestStruct.members.should include(:a, :b, :c)
|
369
|
+
end
|
370
|
+
it "Can return its instance members and values as lists" do
|
371
|
+
class TestStruct < FFI::Struct
|
372
|
+
layout :a, :int, :b, :int, :c, :int
|
373
|
+
end
|
374
|
+
s = TestStruct.new
|
375
|
+
s.members.should include(:a, :b, :c)
|
376
|
+
s[:a] = 1
|
377
|
+
s[:b] = 2
|
378
|
+
s[:c] = 3
|
379
|
+
s.values.should include(1, 2, 3)
|
380
|
+
end
|
381
|
+
it 'should return an ordered field/offset pairs array' do
|
382
|
+
class TestStruct < FFI::Struct
|
383
|
+
layout :a, :int, :b, :int, :c, :int
|
384
|
+
end
|
385
|
+
s = TestStruct.new
|
386
|
+
s.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
|
387
|
+
TestStruct.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
|
388
|
+
end
|
389
|
+
it "Struct#offset_of returns offset of field within struct" do
|
390
|
+
class TestStruct < FFI::Struct
|
391
|
+
layout :a, :int, :b, :int, :c, :int
|
392
|
+
end
|
393
|
+
TestStruct.offset_of(:a).should == 0
|
394
|
+
TestStruct.offset_of(:b).should == 4
|
395
|
+
TestStruct.offset_of(:c).should == 8
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
describe FFI::Struct, ' with a nested struct field' do
|
400
|
+
module LibTest
|
401
|
+
extend FFI::Library
|
402
|
+
ffi_lib TestLibrary::PATH
|
403
|
+
class NestedStruct < FFI::Struct
|
404
|
+
layout :i, :int
|
405
|
+
end
|
406
|
+
class ContainerStruct < FFI::Struct
|
407
|
+
layout :first, :char, :ns, NestedStruct
|
408
|
+
end
|
409
|
+
attach_function :struct_align_nested_struct, [ :pointer ], :int
|
410
|
+
attach_function :struct_make_container_struct, [ :int ], :pointer
|
411
|
+
end
|
412
|
+
before do
|
413
|
+
@cs = LibTest::ContainerStruct.new
|
414
|
+
end
|
415
|
+
it 'should align correctly nested struct field' do
|
416
|
+
@cs[:ns][:i] = 123
|
417
|
+
LibTest.struct_align_nested_struct(@cs.to_ptr).should == 123
|
418
|
+
end
|
419
|
+
it 'should correctly calculate Container size (in bytes)' do
|
420
|
+
LibTest::ContainerStruct.size.should == 8
|
421
|
+
end
|
422
|
+
it 'should return a Struct object when the field is accessed' do
|
423
|
+
@cs[:ns].is_a?(FFI::Struct).should be_true
|
424
|
+
end
|
425
|
+
it 'should read a value from memory' do
|
426
|
+
@cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
|
427
|
+
@cs[:ns][:i].should == 123
|
428
|
+
end
|
429
|
+
it 'should write a value to memory' do
|
430
|
+
@cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
|
431
|
+
@cs[:ns][:i] = 456
|
432
|
+
LibTest.struct_align_nested_struct(@cs.to_ptr).should == 456
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'should be able to assign struct instance to nested field' do
|
436
|
+
cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
|
437
|
+
ns = LibTest::NestedStruct.new
|
438
|
+
ns[:i] = 567
|
439
|
+
cs[:ns] = ns
|
440
|
+
cs[:ns][:i].should == 567
|
441
|
+
LibTest.struct_align_nested_struct(cs.to_ptr).should == 567
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
describe FFI::Struct, ' with a nested array of structs' do
|
446
|
+
module InlineArrayOfStructs
|
447
|
+
extend FFI::Library
|
448
|
+
ffi_lib TestLibrary::PATH
|
449
|
+
class NestedStruct < FFI::Struct
|
450
|
+
layout :i, :int
|
451
|
+
end
|
452
|
+
class ContainerStruct < FFI::Struct
|
453
|
+
layout :first, :char, :ns, [ NestedStruct, 1 ]
|
454
|
+
end
|
455
|
+
attach_function :struct_align_nested_struct, [ :pointer ], :int
|
456
|
+
attach_function :struct_make_container_struct, [ :int ], :pointer
|
457
|
+
end
|
458
|
+
|
459
|
+
before do
|
460
|
+
@cs = InlineArrayOfStructs::ContainerStruct.new
|
461
|
+
end
|
462
|
+
|
463
|
+
it 'should align correctly nested struct field' do
|
464
|
+
@cs[:ns][0][:i] = 123
|
465
|
+
InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 123
|
466
|
+
end
|
467
|
+
|
468
|
+
it 'should correctly calculate Container size (in bytes)' do
|
469
|
+
InlineArrayOfStructs::ContainerStruct.size.should == 8
|
470
|
+
end
|
471
|
+
|
472
|
+
it 'should return a Struct object when the field is accessed' do
|
473
|
+
@cs[:ns][0].is_a?(FFI::Struct).should be_true
|
474
|
+
end
|
475
|
+
|
476
|
+
it 'should read a value from memory' do
|
477
|
+
@cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
|
478
|
+
@cs[:ns][0][:i].should == 123
|
479
|
+
end
|
480
|
+
|
481
|
+
it 'should write a value to memory' do
|
482
|
+
@cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
|
483
|
+
@cs[:ns][0][:i] = 456
|
484
|
+
InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 456
|
485
|
+
end
|
486
|
+
|
487
|
+
it 'should support Enumerable#each' do
|
488
|
+
@cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
|
489
|
+
ints = []
|
490
|
+
@cs[:ns].each { |s| ints << s[:i] }
|
491
|
+
ints[0].should == 123
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
describe FFI::Struct, ' by value' do
|
496
|
+
module LibTest
|
497
|
+
extend FFI::Library
|
498
|
+
ffi_lib TestLibrary::PATH
|
499
|
+
|
500
|
+
class S8S32 < FFI::Struct
|
501
|
+
layout :s8, :char, :s32, :int
|
502
|
+
end
|
503
|
+
|
504
|
+
class StructString < FFI::Struct
|
505
|
+
layout :bytes, :string, :len, :int
|
506
|
+
end
|
507
|
+
|
508
|
+
attach_function :struct_return_s8s32, [ ], S8S32.by_value
|
509
|
+
attach_function :struct_s8s32_set, [ :char, :int ], S8S32.by_value
|
510
|
+
attach_function :struct_s8s32_get_s8, [ S8S32.by_value ], :char
|
511
|
+
attach_function :struct_s8s32_get_s32, [ S8S32.by_value ], :int
|
512
|
+
attach_function :struct_s8s32_s32_ret_s32, [ S8S32.by_value, :int ], :int
|
513
|
+
attach_function :struct_s8s32_s64_ret_s64, [ S8S32.by_value, :long_long ], :long_long
|
514
|
+
attach_function :struct_s8s32_ret_s8s32, [ S8S32.by_value ], S8S32.by_value
|
515
|
+
attach_function :struct_s32_ptr_s32_s8s32_ret_s32, [ :int, :pointer, :int, S8S32.by_value ], :int
|
516
|
+
attach_function :struct_varargs_ret_struct_string, [ :int, :varargs ], StructString.by_value
|
517
|
+
end
|
518
|
+
|
519
|
+
it 'return using pre-set values' do
|
520
|
+
s = LibTest.struct_return_s8s32
|
521
|
+
s[:s8].should == 0x7f
|
522
|
+
s[:s32].should == 0x12345678
|
523
|
+
end
|
524
|
+
|
525
|
+
it 'return using passed in values' do
|
526
|
+
s = LibTest.struct_s8s32_set(123, 456789)
|
527
|
+
s[:s8].should == 123
|
528
|
+
s[:s32].should == 456789
|
529
|
+
end
|
530
|
+
|
531
|
+
it 'parameter' do
|
532
|
+
s = LibTest::S8S32.new
|
533
|
+
s[:s8] = 0x12
|
534
|
+
s[:s32] = 0x34567890
|
535
|
+
LibTest.struct_s8s32_get_s8(s).should == 0x12
|
536
|
+
LibTest.struct_s8s32_get_s32(s).should == 0x34567890
|
537
|
+
end
|
538
|
+
|
539
|
+
it 'parameter with following s32' do
|
540
|
+
s = LibTest::S8S32.new
|
541
|
+
s[:s8] = 0x12
|
542
|
+
s[:s32] = 0x34567890
|
543
|
+
|
544
|
+
LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead
|
545
|
+
end
|
546
|
+
|
547
|
+
it 'parameter with following s64' do
|
548
|
+
s = LibTest::S8S32.new
|
549
|
+
s[:s8] = 0x12
|
550
|
+
s[:s32] = 0x34567890
|
551
|
+
end
|
552
|
+
|
553
|
+
it 'parameter with preceding s32,ptr,s32' do
|
554
|
+
s = LibTest::S8S32.new
|
555
|
+
s[:s8] = 0x12
|
556
|
+
s[:s32] = 0x34567890
|
557
|
+
out = LibTest::S8S32.new
|
558
|
+
LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890
|
559
|
+
out[:s8].should == s[:s8]
|
560
|
+
out[:s32].should == s[:s32]
|
561
|
+
end
|
562
|
+
|
563
|
+
it 'parameter with preceding s32,string,s32' do
|
564
|
+
s = LibTest::S8S32.new
|
565
|
+
s[:s8] = 0x12
|
566
|
+
s[:s32] = 0x34567890
|
567
|
+
out = 0.chr * 32
|
568
|
+
LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890
|
569
|
+
end
|
570
|
+
|
571
|
+
it 'parameter, returning struct by value' do
|
572
|
+
s = LibTest::S8S32.new
|
573
|
+
s[:s8] = 0x12
|
574
|
+
s[:s32] = 0x34567890
|
575
|
+
|
576
|
+
ret = LibTest.struct_s8s32_ret_s8s32(s)
|
577
|
+
ret[:s8].should == s[:s8]
|
578
|
+
ret[:s32].should == s[:s32]
|
579
|
+
end
|
580
|
+
|
581
|
+
it 'varargs returning a struct' do
|
582
|
+
string = "test"
|
583
|
+
s = LibTest.struct_varargs_ret_struct_string(4, :string, string)
|
584
|
+
s[:len].should == string.length
|
585
|
+
s[:bytes].should == string
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
describe FFI::Struct, ' with an array field' do
|
590
|
+
module LibTest
|
591
|
+
extend FFI::Library
|
592
|
+
ffi_lib TestLibrary::PATH
|
593
|
+
class StructWithArray < FFI::Struct
|
594
|
+
layout :first, :char, :a, [:int, 5]
|
595
|
+
end
|
596
|
+
attach_function :struct_make_struct_with_array, [:int, :int, :int, :int, :int], :pointer
|
597
|
+
attach_function :struct_field_array, [:pointer], :pointer
|
598
|
+
end
|
599
|
+
before do
|
600
|
+
@s = LibTest::StructWithArray.new
|
601
|
+
end
|
602
|
+
it 'should correctly calculate StructWithArray size (in bytes)' do
|
603
|
+
LibTest::StructWithArray.size.should == 24
|
604
|
+
end
|
605
|
+
it 'should read values from memory' do
|
606
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
607
|
+
@s[:a].to_a.should == [0, 1, 2, 3, 4]
|
608
|
+
end
|
609
|
+
# it 'should cache array object for successive calls' do
|
610
|
+
# @s[:a].object_id.should == @s[:a].object_id
|
611
|
+
# end
|
612
|
+
it 'should return the number of elements in the array field' do
|
613
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
614
|
+
@s[:a].size.should == 5
|
615
|
+
end
|
616
|
+
it 'should allow iteration through the array elements' do
|
617
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
618
|
+
@s[:a].each_with_index { |elem, i| elem.should == i }
|
619
|
+
end
|
620
|
+
it 'should return the pointer to the array' do
|
621
|
+
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
622
|
+
@s[:a].to_ptr.should == LibTest::struct_field_array(@s.to_ptr)
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
describe 'BuggedStruct' do
|
627
|
+
module LibTest
|
628
|
+
extend FFI::Library
|
629
|
+
ffi_lib TestLibrary::PATH
|
630
|
+
class BuggedStruct < FFI::Struct
|
631
|
+
layout :visible, :uchar,
|
632
|
+
:x, :uint,
|
633
|
+
:y, :uint,
|
634
|
+
:rx, :short,
|
635
|
+
:ry, :short,
|
636
|
+
:order, :uchar,
|
637
|
+
:size, :uchar
|
638
|
+
end
|
639
|
+
attach_function :bugged_struct_size, [], :uint
|
640
|
+
end
|
641
|
+
it 'should return its correct size' do
|
642
|
+
LibTest::BuggedStruct.size.should == LibTest.bugged_struct_size
|
643
|
+
end
|
644
|
+
it "offsets within struct should be correct" do
|
645
|
+
LibTest::BuggedStruct.offset_of(:visible).should == 0
|
646
|
+
LibTest::BuggedStruct.offset_of(:x).should == 4
|
647
|
+
LibTest::BuggedStruct.offset_of(:y).should == 8
|
648
|
+
LibTest::BuggedStruct.offset_of(:rx).should == 12
|
649
|
+
LibTest::BuggedStruct.offset_of(:ry).should == 14
|
650
|
+
LibTest::BuggedStruct.offset_of(:order).should == 16
|
651
|
+
LibTest::BuggedStruct.offset_of(:size).should == 17
|
652
|
+
end
|
653
|
+
it 'should return correct field/offset pairs' do
|
654
|
+
LibTest::BuggedStruct.offsets.sort do |a, b|
|
655
|
+
a[1] <=> b[1]
|
656
|
+
end.should == [[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]]
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
describe "Struct allocation" do
|
661
|
+
it "MemoryPointer.new(Struct, 2)" do
|
662
|
+
class S < FFI::Struct
|
663
|
+
layout :i, :uint
|
664
|
+
end
|
665
|
+
p = FFI::MemoryPointer.new(S, 2)
|
666
|
+
p.total.should == 8
|
667
|
+
p.type_size.should == 4
|
668
|
+
p.put_uint(4, 0xdeadbeef)
|
669
|
+
S.new(p[1])[:i].should == 0xdeadbeef
|
670
|
+
p[1].address.should == (p[0].address + 4)
|
671
|
+
end
|
672
|
+
|
673
|
+
it "Buffer.new(Struct, 2)" do
|
674
|
+
class S < FFI::Struct
|
675
|
+
layout :i, :uint
|
676
|
+
end
|
677
|
+
p = FFI::Buffer.new(S, 2)
|
678
|
+
p.total.should == 8
|
679
|
+
p.type_size.should == 4
|
680
|
+
p.put_uint(4, 0xdeadbeef)
|
681
|
+
S.new(p[1])[:i].should == 0xdeadbeef
|
682
|
+
end
|
683
|
+
|
684
|
+
it "null? should be true when initialized with NULL pointer" do
|
685
|
+
class S < FFI::Struct
|
686
|
+
layout :i, :uint
|
687
|
+
end
|
688
|
+
S.new(FFI::Pointer::NULL).null?.should be_true
|
689
|
+
end
|
690
|
+
|
691
|
+
it "null? should be false when initialized with non-NULL pointer" do
|
692
|
+
class S < FFI::Struct
|
693
|
+
layout :i, :uint
|
694
|
+
end
|
695
|
+
S.new(FFI::MemoryPointer.new(S)).null?.should be_false
|
696
|
+
end
|
697
|
+
|
698
|
+
it "supports :bool as a struct member" do
|
699
|
+
lambda do
|
700
|
+
c = Class.new(FFI::Struct) do
|
701
|
+
layout :b, :bool
|
702
|
+
end
|
703
|
+
struct = c.new
|
704
|
+
struct[:b] = ! struct[:b]
|
705
|
+
end.should_not raise_error
|
706
|
+
end
|
707
|
+
|
708
|
+
end
|
709
|
+
|
710
|
+
describe "variable-length arrays" do
|
711
|
+
it "zero length array should be accepted as last field" do
|
712
|
+
lambda {
|
713
|
+
Class.new(FFI::Struct) do
|
714
|
+
layout :count, :int, :data, [ :char, 0 ]
|
715
|
+
end
|
716
|
+
}.should_not raise_error
|
717
|
+
end
|
718
|
+
|
719
|
+
it "zero length array before last element should raise error" do
|
720
|
+
lambda {
|
721
|
+
Class.new(FFI::Struct) do
|
722
|
+
layout :data, [ :char, 0 ], :count, :int
|
723
|
+
end
|
724
|
+
}.should raise_error
|
725
|
+
end
|
726
|
+
|
727
|
+
it "can access elements of array" do
|
728
|
+
struct_class = Class.new(FFI::Struct) do
|
729
|
+
layout :count, :int, :data, [ :long, 0 ]
|
730
|
+
end
|
731
|
+
s = struct_class.new(FFI::MemoryPointer.new(1024))
|
732
|
+
s[:data][0] = 0x1eadbeef
|
733
|
+
s[:data][1] = 0x12345678
|
734
|
+
s[:data][0].should == 0x1eadbeef
|
735
|
+
s[:data][1].should == 0x12345678
|
736
|
+
end
|
737
|
+
|
738
|
+
it "non-variable length array is bounds checked" do
|
739
|
+
struct_class = Class.new(FFI::Struct) do
|
740
|
+
layout :count, :int, :data, [ :long, 1 ]
|
741
|
+
end
|
742
|
+
s = struct_class.new(FFI::MemoryPointer.new(1024))
|
743
|
+
s[:data][0] = 0x1eadbeef
|
744
|
+
lambda { s[:data][1] = 0x12345678 }.should raise_error
|
745
|
+
s[:data][0].should == 0x1eadbeef
|
746
|
+
lambda { s[:data][1].should == 0x12345678 }.should raise_error
|
747
|
+
end
|
748
|
+
end
|