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
data/ext/ffi_c/Call.c
ADDED
@@ -0,0 +1,853 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2009, Wayne Meissner
|
3
|
+
* Copyright (c) 2009, Luc Heinrich <luc@honk-honk.com>
|
4
|
+
* Copyright (c) 2009, Mike Dalessio <mike.dalessio@gmail.com>
|
5
|
+
* Copyright (c) 2009, Aman Gupta.
|
6
|
+
* All rights reserved.
|
7
|
+
*
|
8
|
+
* Redistribution and use in source and binary forms, with or without
|
9
|
+
* modification, are permitted provided that the following conditions are met:
|
10
|
+
*
|
11
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
12
|
+
* list of conditions and the following disclaimer.
|
13
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
14
|
+
* this list of conditions and the following disclaimer in the documentation
|
15
|
+
* and/or other materials provided with the distribution.
|
16
|
+
* * The name of the author or authors may not be used to endorse or promote
|
17
|
+
* products derived from this software without specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#include <sys/param.h>
|
32
|
+
#include <sys/types.h>
|
33
|
+
#include <stdio.h>
|
34
|
+
#include <stdint.h>
|
35
|
+
#include <stdbool.h>
|
36
|
+
#include <errno.h>
|
37
|
+
#include <ruby.h>
|
38
|
+
#if defined(HAVE_NATIVETHREAD) && defined(HAVE_RB_THREAD_BLOCKING_REGION) && !defined(_WIN32)
|
39
|
+
# include <signal.h>
|
40
|
+
# include <pthread.h>
|
41
|
+
#endif
|
42
|
+
#include <ffi.h>
|
43
|
+
#include "extconf.h"
|
44
|
+
#include "rbffi.h"
|
45
|
+
#include "compat.h"
|
46
|
+
#include "AbstractMemory.h"
|
47
|
+
#include "Pointer.h"
|
48
|
+
#include "Struct.h"
|
49
|
+
#include "Function.h"
|
50
|
+
#include "Type.h"
|
51
|
+
#include "LastError.h"
|
52
|
+
#include "Call.h"
|
53
|
+
|
54
|
+
#ifdef USE_RAW
|
55
|
+
# ifndef __i386__
|
56
|
+
# error "RAW argument packing only supported on i386"
|
57
|
+
# endif
|
58
|
+
|
59
|
+
#define INT8_ADJ (4)
|
60
|
+
#define INT16_ADJ (4)
|
61
|
+
#define INT32_ADJ (4)
|
62
|
+
#define INT64_ADJ (8)
|
63
|
+
#define FLOAT32_ADJ (4)
|
64
|
+
#define FLOAT64_ADJ (8)
|
65
|
+
#define ADDRESS_ADJ (sizeof(void *))
|
66
|
+
|
67
|
+
#endif /* USE_RAW */
|
68
|
+
|
69
|
+
#ifdef USE_RAW
|
70
|
+
# define ADJ(p, a) ((p) = (FFIStorage*) (((char *) p) + a##_ADJ))
|
71
|
+
#else
|
72
|
+
# define ADJ(p, a) (++(p))
|
73
|
+
#endif
|
74
|
+
|
75
|
+
static void* callback_param(VALUE proc, VALUE cbinfo);
|
76
|
+
static inline int getSignedInt(VALUE value, int type, int minValue, int maxValue, const char* typeName, VALUE enums);
|
77
|
+
static inline int getUnsignedInt(VALUE value, int type, int maxValue, const char* typeName);
|
78
|
+
static inline unsigned int getUnsignedInt32(VALUE value, int type);
|
79
|
+
static inline void* getPointer(VALUE value, int type);
|
80
|
+
static inline char* getString(VALUE value, int type);
|
81
|
+
|
82
|
+
|
83
|
+
#ifdef BYPASS_FFI
|
84
|
+
static long rbffi_GetLongValue(int idx, VALUE* argv, FunctionType* fnInfo);
|
85
|
+
static VALUE rbffi_InvokeVrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
86
|
+
static VALUE rbffi_InvokeLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
87
|
+
static VALUE rbffi_InvokeLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
88
|
+
static VALUE rbffi_InvokeLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
89
|
+
static VALUE rbffi_InvokeLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
90
|
+
static VALUE rbffi_InvokeLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
91
|
+
static VALUE rbffi_InvokeLLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
92
|
+
static VALUE rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
|
93
|
+
#endif
|
94
|
+
|
95
|
+
|
96
|
+
static ID id_to_ptr, id_map_symbol;
|
97
|
+
|
98
|
+
void
|
99
|
+
rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTypes,
|
100
|
+
FFIStorage* paramStorage, void** ffiValues,
|
101
|
+
VALUE* callbackParameters, int callbackCount, VALUE enums)
|
102
|
+
{
|
103
|
+
VALUE callbackProc = Qnil;
|
104
|
+
FFIStorage* param = ¶mStorage[0];
|
105
|
+
int i, argidx, cbidx, argCount;
|
106
|
+
|
107
|
+
if (paramCount != -1 && paramCount != argc) {
|
108
|
+
if (argc == (paramCount - 1) && callbackCount == 1 && rb_block_given_p()) {
|
109
|
+
callbackProc = rb_block_proc();
|
110
|
+
} else {
|
111
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, paramCount);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
argCount = paramCount != -1 ? paramCount : argc;
|
116
|
+
|
117
|
+
for (i = 0, argidx = 0, cbidx = 0; i < argCount; ++i) {
|
118
|
+
int type = argidx < argc ? TYPE(argv[argidx]) : T_NONE;
|
119
|
+
ffiValues[i] = param;
|
120
|
+
|
121
|
+
switch (paramTypes[i]) {
|
122
|
+
|
123
|
+
case NATIVE_INT8:
|
124
|
+
param->s8 = getSignedInt(argv[argidx++], type, -128, 127, "char", Qnil);
|
125
|
+
ADJ(param, INT8);
|
126
|
+
break;
|
127
|
+
|
128
|
+
|
129
|
+
case NATIVE_INT16:
|
130
|
+
param->s16 = getSignedInt(argv[argidx++], type, -0x8000, 0x7fff, "short", Qnil);
|
131
|
+
ADJ(param, INT16);
|
132
|
+
break;
|
133
|
+
|
134
|
+
|
135
|
+
case NATIVE_INT32:
|
136
|
+
case NATIVE_ENUM:
|
137
|
+
param->s32 = getSignedInt(argv[argidx++], type, -0x80000000, 0x7fffffff, "int", enums);
|
138
|
+
ADJ(param, INT32);
|
139
|
+
break;
|
140
|
+
|
141
|
+
|
142
|
+
case NATIVE_BOOL:
|
143
|
+
if (type != T_TRUE && type != T_FALSE) {
|
144
|
+
rb_raise(rb_eTypeError, "Expected a Boolean parameter");
|
145
|
+
}
|
146
|
+
param->s32 = argv[argidx++] == Qtrue;
|
147
|
+
ADJ(param, INT32);
|
148
|
+
break;
|
149
|
+
|
150
|
+
|
151
|
+
case NATIVE_UINT8:
|
152
|
+
param->u8 = getUnsignedInt(argv[argidx++], type, 0xff, "unsigned char");
|
153
|
+
ADJ(param, INT8);
|
154
|
+
break;
|
155
|
+
|
156
|
+
|
157
|
+
case NATIVE_UINT16:
|
158
|
+
param->u16 = getUnsignedInt(argv[argidx++], type, 0xffff, "unsigned short");
|
159
|
+
ADJ(param, INT16);
|
160
|
+
break;
|
161
|
+
|
162
|
+
|
163
|
+
case NATIVE_UINT32:
|
164
|
+
/* Special handling/checking for unsigned 32 bit integers */
|
165
|
+
param->u32 = getUnsignedInt32(argv[argidx++], type);
|
166
|
+
ADJ(param, INT32);
|
167
|
+
break;
|
168
|
+
|
169
|
+
|
170
|
+
case NATIVE_INT64:
|
171
|
+
if (type != T_FIXNUM && type != T_BIGNUM) {
|
172
|
+
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
173
|
+
}
|
174
|
+
param->i64 = NUM2LL(argv[argidx]);
|
175
|
+
ADJ(param, INT64);
|
176
|
+
++argidx;
|
177
|
+
break;
|
178
|
+
|
179
|
+
|
180
|
+
case NATIVE_UINT64:
|
181
|
+
if (type != T_FIXNUM && type != T_BIGNUM) {
|
182
|
+
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
183
|
+
}
|
184
|
+
param->u64 = NUM2ULL(argv[argidx]);
|
185
|
+
ADJ(param, INT64);
|
186
|
+
++argidx;
|
187
|
+
break;
|
188
|
+
|
189
|
+
|
190
|
+
case NATIVE_FLOAT32:
|
191
|
+
if (type != T_FLOAT && type != T_FIXNUM) {
|
192
|
+
rb_raise(rb_eTypeError, "Expected a Float parameter");
|
193
|
+
}
|
194
|
+
param->f32 = (float) NUM2DBL(argv[argidx]);
|
195
|
+
ADJ(param, FLOAT32);
|
196
|
+
++argidx;
|
197
|
+
break;
|
198
|
+
|
199
|
+
case NATIVE_FLOAT64:
|
200
|
+
if (type != T_FLOAT && type != T_FIXNUM) {
|
201
|
+
rb_raise(rb_eTypeError, "Expected a Float parameter");
|
202
|
+
}
|
203
|
+
param->f64 = NUM2DBL(argv[argidx]);
|
204
|
+
ADJ(param, FLOAT64);
|
205
|
+
++argidx;
|
206
|
+
break;
|
207
|
+
|
208
|
+
|
209
|
+
case NATIVE_STRING:
|
210
|
+
param->ptr = getString(argv[argidx++], type);
|
211
|
+
ADJ(param, ADDRESS);
|
212
|
+
break;
|
213
|
+
|
214
|
+
case NATIVE_POINTER:
|
215
|
+
case NATIVE_BUFFER_IN:
|
216
|
+
case NATIVE_BUFFER_OUT:
|
217
|
+
case NATIVE_BUFFER_INOUT:
|
218
|
+
param->ptr = getPointer(argv[argidx++], type);
|
219
|
+
ADJ(param, ADDRESS);
|
220
|
+
break;
|
221
|
+
|
222
|
+
|
223
|
+
case NATIVE_FUNCTION:
|
224
|
+
case NATIVE_CALLBACK:
|
225
|
+
if (callbackProc != Qnil) {
|
226
|
+
param->ptr = callback_param(callbackProc, callbackParameters[cbidx++]);
|
227
|
+
} else {
|
228
|
+
param->ptr = callback_param(argv[argidx], callbackParameters[cbidx++]);
|
229
|
+
++argidx;
|
230
|
+
}
|
231
|
+
ADJ(param, ADDRESS);
|
232
|
+
break;
|
233
|
+
|
234
|
+
case NATIVE_STRUCT:
|
235
|
+
ffiValues[i] = getPointer(argv[argidx++], type);
|
236
|
+
break;
|
237
|
+
|
238
|
+
default:
|
239
|
+
rb_raise(rb_eArgError, "Invalid parameter type: %d", paramTypes[i]);
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
|
244
|
+
|
245
|
+
#if defined(HAVE_NATIVETHREAD) && defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
246
|
+
|
247
|
+
typedef struct BlockingCall_ {
|
248
|
+
void* function;
|
249
|
+
FunctionType* info;
|
250
|
+
void **ffiValues;
|
251
|
+
FFIStorage* retval;
|
252
|
+
} BlockingCall;
|
253
|
+
|
254
|
+
static VALUE
|
255
|
+
call_blocking_function(void* data)
|
256
|
+
{
|
257
|
+
BlockingCall* b = (BlockingCall *) data;
|
258
|
+
|
259
|
+
ffi_call(&b->info->ffi_cif, FFI_FN(b->function), b->retval, b->ffiValues);
|
260
|
+
|
261
|
+
return Qnil;
|
262
|
+
}
|
263
|
+
#endif
|
264
|
+
|
265
|
+
VALUE
|
266
|
+
rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
267
|
+
{
|
268
|
+
void* retval;
|
269
|
+
void** ffiValues;
|
270
|
+
FFIStorage* params;
|
271
|
+
|
272
|
+
ffiValues = ALLOCA_N(void *, fnInfo->parameterCount);
|
273
|
+
params = ALLOCA_N(FFIStorage, fnInfo->parameterCount);
|
274
|
+
retval = alloca(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
|
275
|
+
|
276
|
+
rbffi_SetupCallParams(argc, argv,
|
277
|
+
fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues,
|
278
|
+
fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
|
279
|
+
|
280
|
+
#if defined(HAVE_NATIVETHREAD) && defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
281
|
+
if (unlikely(fnInfo->blocking)) {
|
282
|
+
BlockingCall bc;
|
283
|
+
|
284
|
+
bc.info = fnInfo;
|
285
|
+
bc.function = function;
|
286
|
+
bc.ffiValues = ffiValues;
|
287
|
+
bc.retval = retval;
|
288
|
+
|
289
|
+
rb_thread_blocking_region(call_blocking_function, &bc, (void *) -1, NULL);
|
290
|
+
} else {
|
291
|
+
ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues);
|
292
|
+
}
|
293
|
+
#else
|
294
|
+
ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues);
|
295
|
+
#endif
|
296
|
+
|
297
|
+
if (!fnInfo->ignoreErrno) {
|
298
|
+
rbffi_save_errno();
|
299
|
+
}
|
300
|
+
|
301
|
+
return rbffi_NativeValue_ToRuby(fnInfo->returnType, fnInfo->rbReturnType, retval,
|
302
|
+
fnInfo->rbEnums);
|
303
|
+
}
|
304
|
+
|
305
|
+
static inline int
|
306
|
+
getSignedInt(VALUE value, int type, int minValue, int maxValue, const char* typeName, VALUE enums)
|
307
|
+
{
|
308
|
+
int i;
|
309
|
+
|
310
|
+
if (type == T_SYMBOL && enums != Qnil) {
|
311
|
+
value = rb_funcall2(enums, id_map_symbol, 1, &value);
|
312
|
+
if (value == Qnil) {
|
313
|
+
rb_raise(rb_eTypeError, "Expected a valid enum constant");
|
314
|
+
}
|
315
|
+
|
316
|
+
} else if (type != T_FIXNUM && type != T_BIGNUM) {
|
317
|
+
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
318
|
+
}
|
319
|
+
|
320
|
+
i = NUM2INT(value);
|
321
|
+
if (i < minValue || i > maxValue) {
|
322
|
+
rb_raise(rb_eRangeError, "Value %d outside %s range", i, typeName);
|
323
|
+
}
|
324
|
+
|
325
|
+
return i;
|
326
|
+
}
|
327
|
+
|
328
|
+
static inline int
|
329
|
+
getUnsignedInt(VALUE value, int type, int maxValue, const char* typeName)
|
330
|
+
{
|
331
|
+
int i;
|
332
|
+
|
333
|
+
if (type != T_FIXNUM && type != T_BIGNUM) {
|
334
|
+
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
335
|
+
}
|
336
|
+
|
337
|
+
i = NUM2INT(value);
|
338
|
+
if (i < 0 || i > maxValue) {
|
339
|
+
rb_raise(rb_eRangeError, "Value %d outside %s range", i, typeName);
|
340
|
+
}
|
341
|
+
|
342
|
+
return i;
|
343
|
+
}
|
344
|
+
|
345
|
+
/* Special handling/checking for unsigned 32 bit integers */
|
346
|
+
static inline unsigned int
|
347
|
+
getUnsignedInt32(VALUE value, int type)
|
348
|
+
{
|
349
|
+
long long i;
|
350
|
+
|
351
|
+
if (type != T_FIXNUM && type != T_BIGNUM) {
|
352
|
+
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
353
|
+
}
|
354
|
+
|
355
|
+
i = NUM2LL(value);
|
356
|
+
if (i < 0L || i > 0xffffffffL) {
|
357
|
+
rb_raise(rb_eRangeError, "Value %lld outside unsigned int range", i);
|
358
|
+
}
|
359
|
+
|
360
|
+
return (unsigned int) i;
|
361
|
+
}
|
362
|
+
|
363
|
+
static inline void*
|
364
|
+
getPointer(VALUE value, int type)
|
365
|
+
{
|
366
|
+
if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_AbstractMemoryClass)) {
|
367
|
+
|
368
|
+
return ((AbstractMemory *) DATA_PTR(value))->address;
|
369
|
+
|
370
|
+
} else if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_StructClass)) {
|
371
|
+
|
372
|
+
AbstractMemory* memory = ((Struct *) DATA_PTR(value))->pointer;
|
373
|
+
return memory != NULL ? memory->address : NULL;
|
374
|
+
|
375
|
+
} else if (type == T_STRING) {
|
376
|
+
|
377
|
+
if (rb_safe_level() >= 1 && OBJ_TAINTED(value)) {
|
378
|
+
rb_raise(rb_eSecurityError, "Unsafe string parameter");
|
379
|
+
}
|
380
|
+
return StringValuePtr(value);
|
381
|
+
|
382
|
+
} else if (type == T_NIL) {
|
383
|
+
|
384
|
+
return NULL;
|
385
|
+
|
386
|
+
} else if (rb_respond_to(value, id_to_ptr)) {
|
387
|
+
|
388
|
+
VALUE ptr = rb_funcall2(value, id_to_ptr, 0, NULL);
|
389
|
+
if (rb_obj_is_kind_of(ptr, rbffi_AbstractMemoryClass) && TYPE(ptr) == T_DATA) {
|
390
|
+
return ((AbstractMemory *) DATA_PTR(ptr))->address;
|
391
|
+
}
|
392
|
+
rb_raise(rb_eArgError, "to_ptr returned an invalid pointer");
|
393
|
+
}
|
394
|
+
|
395
|
+
rb_raise(rb_eArgError, ":pointer argument is not a valid pointer");
|
396
|
+
return NULL;
|
397
|
+
}
|
398
|
+
|
399
|
+
static inline char*
|
400
|
+
getString(VALUE value, int type)
|
401
|
+
{
|
402
|
+
if (type == T_STRING) {
|
403
|
+
|
404
|
+
if (rb_safe_level() >= 1 && OBJ_TAINTED(value)) {
|
405
|
+
rb_raise(rb_eSecurityError, "Unsafe string parameter");
|
406
|
+
}
|
407
|
+
|
408
|
+
return StringValueCStr(value);
|
409
|
+
|
410
|
+
} else if (type == T_NIL) {
|
411
|
+
return NULL;
|
412
|
+
}
|
413
|
+
|
414
|
+
rb_raise(rb_eArgError, "Invalid String value");
|
415
|
+
}
|
416
|
+
|
417
|
+
|
418
|
+
Invoker
|
419
|
+
rbffi_GetInvoker(FunctionType *fnInfo)
|
420
|
+
{
|
421
|
+
#if defined(BYPASS_FFI) && (defined(__i386__) || defined(__x86_64__))
|
422
|
+
int i;
|
423
|
+
bool fastLong = fnInfo->abi == FFI_DEFAULT_ABI && !fnInfo->blocking && !fnInfo->hasStruct;
|
424
|
+
|
425
|
+
switch (fnInfo->returnType->nativeType) {
|
426
|
+
case NATIVE_VOID:
|
427
|
+
case NATIVE_BOOL:
|
428
|
+
case NATIVE_INT8:
|
429
|
+
case NATIVE_UINT8:
|
430
|
+
case NATIVE_INT16:
|
431
|
+
case NATIVE_UINT16:
|
432
|
+
case NATIVE_INT32:
|
433
|
+
case NATIVE_UINT32:
|
434
|
+
#ifdef __x86_64__
|
435
|
+
case NATIVE_INT64:
|
436
|
+
case NATIVE_UINT64:
|
437
|
+
#endif
|
438
|
+
case NATIVE_STRING:
|
439
|
+
case NATIVE_POINTER:
|
440
|
+
break;
|
441
|
+
default:
|
442
|
+
fastLong = false;
|
443
|
+
break;
|
444
|
+
}
|
445
|
+
|
446
|
+
for (i = 0; fastLong && i < fnInfo->parameterCount; ++i) {
|
447
|
+
switch (fnInfo->nativeParameterTypes[i]) {
|
448
|
+
case NATIVE_BOOL:
|
449
|
+
case NATIVE_INT8:
|
450
|
+
case NATIVE_UINT8:
|
451
|
+
case NATIVE_INT16:
|
452
|
+
case NATIVE_UINT16:
|
453
|
+
case NATIVE_INT32:
|
454
|
+
case NATIVE_UINT32:
|
455
|
+
#ifdef __x86_64__
|
456
|
+
case NATIVE_INT64:
|
457
|
+
case NATIVE_UINT64:
|
458
|
+
#endif
|
459
|
+
case NATIVE_STRING:
|
460
|
+
case NATIVE_POINTER:
|
461
|
+
case NATIVE_BUFFER_IN:
|
462
|
+
case NATIVE_BUFFER_OUT:
|
463
|
+
case NATIVE_BUFFER_INOUT:
|
464
|
+
case NATIVE_FUNCTION:
|
465
|
+
case NATIVE_CALLBACK:
|
466
|
+
break;
|
467
|
+
default:
|
468
|
+
fastLong = false;
|
469
|
+
break;
|
470
|
+
}
|
471
|
+
}
|
472
|
+
|
473
|
+
if (fastLong && fnInfo->callbackCount < 1) {
|
474
|
+
switch (fnInfo->parameterCount) {
|
475
|
+
case 0:
|
476
|
+
return rbffi_InvokeVrL;
|
477
|
+
case 1:
|
478
|
+
return rbffi_InvokeLrL;
|
479
|
+
case 2:
|
480
|
+
return rbffi_InvokeLLrL;
|
481
|
+
case 3:
|
482
|
+
return rbffi_InvokeLLLrL;
|
483
|
+
case 4:
|
484
|
+
return rbffi_InvokeLLLLrL;
|
485
|
+
case 5:
|
486
|
+
return rbffi_InvokeLLLLLrL;
|
487
|
+
case 6:
|
488
|
+
return rbffi_InvokeLLLLLLrL;
|
489
|
+
|
490
|
+
default:
|
491
|
+
break;
|
492
|
+
}
|
493
|
+
|
494
|
+
} else if (fastLong && fnInfo->parameterCount <= 6) {
|
495
|
+
return rbffi_InvokeLongParams;
|
496
|
+
}
|
497
|
+
#endif
|
498
|
+
|
499
|
+
return rbffi_CallFunction;
|
500
|
+
}
|
501
|
+
|
502
|
+
#if defined(BYPASS_FFI) && (defined(__i386__) || defined(__x86_64__))
|
503
|
+
typedef long L;
|
504
|
+
|
505
|
+
static long
|
506
|
+
rbffi_GetLongValue(int idx, VALUE* argv, FunctionType* fnInfo)
|
507
|
+
{
|
508
|
+
VALUE value = argv[idx];
|
509
|
+
NativeType nativeType = fnInfo->nativeParameterTypes[idx];
|
510
|
+
int type = TYPE(value);
|
511
|
+
|
512
|
+
switch (nativeType) {
|
513
|
+
case NATIVE_INT8:
|
514
|
+
return getSignedInt(value, type, -128, 127, "char", fnInfo->rbEnums);
|
515
|
+
|
516
|
+
case NATIVE_INT16:
|
517
|
+
return getSignedInt(value, type, -0x8000, 0x7fff, "short", fnInfo->rbEnums);
|
518
|
+
|
519
|
+
case NATIVE_INT32:
|
520
|
+
case NATIVE_ENUM:
|
521
|
+
return getSignedInt(value, type, -0x80000000, 0x7fffffff, "int", fnInfo->rbEnums);
|
522
|
+
|
523
|
+
case NATIVE_BOOL:
|
524
|
+
if (type != T_TRUE && type != T_FALSE) {
|
525
|
+
rb_raise(rb_eTypeError, "Expected a Boolean parameter");
|
526
|
+
}
|
527
|
+
return RTEST(value) ? 1 : 0;
|
528
|
+
|
529
|
+
case NATIVE_UINT8:
|
530
|
+
return getUnsignedInt(value, type, 0xff, "unsigned char");
|
531
|
+
|
532
|
+
case NATIVE_UINT16:
|
533
|
+
return getUnsignedInt(value, type, 0xffff, "unsigned short");
|
534
|
+
|
535
|
+
case NATIVE_UINT32:
|
536
|
+
/* Special handling/checking for unsigned 32 bit integers */
|
537
|
+
return getUnsignedInt32(value, type);
|
538
|
+
|
539
|
+
#ifdef __x86_64__
|
540
|
+
case NATIVE_INT64:
|
541
|
+
if (type != T_FIXNUM && type != T_BIGNUM) {
|
542
|
+
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
543
|
+
}
|
544
|
+
return NUM2LL(value);
|
545
|
+
|
546
|
+
case NATIVE_UINT64:
|
547
|
+
if (type != T_FIXNUM && type != T_BIGNUM) {
|
548
|
+
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
549
|
+
}
|
550
|
+
return NUM2ULL(value);
|
551
|
+
#endif
|
552
|
+
case NATIVE_STRING:
|
553
|
+
return (intptr_t) getString(value, type);
|
554
|
+
|
555
|
+
case NATIVE_POINTER:
|
556
|
+
case NATIVE_BUFFER_IN:
|
557
|
+
case NATIVE_BUFFER_OUT:
|
558
|
+
case NATIVE_BUFFER_INOUT:
|
559
|
+
return (intptr_t) getPointer(value, type);
|
560
|
+
|
561
|
+
default:
|
562
|
+
rb_raise(rb_eTypeError, "unsupported integer type %d", nativeType);
|
563
|
+
return 0;
|
564
|
+
}
|
565
|
+
}
|
566
|
+
|
567
|
+
static inline void
|
568
|
+
checkArity(int argc, int arity) {
|
569
|
+
if (unlikely(argc != arity)) {
|
570
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, arity);
|
571
|
+
}
|
572
|
+
}
|
573
|
+
|
574
|
+
static inline bool
|
575
|
+
isLongValue(VALUE value)
|
576
|
+
{
|
577
|
+
int type = TYPE(value);
|
578
|
+
|
579
|
+
return type == T_FIXNUM || type == T_BIGNUM
|
580
|
+
|| type == T_STRING || type == T_NIL
|
581
|
+
|| (type == T_DATA && rb_obj_is_kind_of(value, rbffi_AbstractMemoryClass))
|
582
|
+
|| (type == T_DATA && rb_obj_is_kind_of(value, rbffi_StructClass))
|
583
|
+
|| rb_respond_to(value, id_to_ptr);
|
584
|
+
}
|
585
|
+
|
586
|
+
static VALUE
|
587
|
+
returnL(FunctionType* fnInfo, L* result)
|
588
|
+
{
|
589
|
+
if (unlikely(!fnInfo->ignoreErrno)) {
|
590
|
+
rbffi_save_errno();
|
591
|
+
}
|
592
|
+
|
593
|
+
/*
|
594
|
+
* This needs to do custom boxing of the return value, since a function
|
595
|
+
* may only fill out the lower 8, 16 or 32 bits of %al, %ah, %eax, %rax, and
|
596
|
+
* the upper part will be garbage. This will truncate the value again, then
|
597
|
+
* sign extend it.
|
598
|
+
*/
|
599
|
+
switch (fnInfo->returnType->nativeType) {
|
600
|
+
case NATIVE_VOID:
|
601
|
+
return Qnil;
|
602
|
+
|
603
|
+
case NATIVE_INT8:
|
604
|
+
return INT2NUM(*(signed char *) result);
|
605
|
+
|
606
|
+
case NATIVE_INT16:
|
607
|
+
return INT2NUM(*(signed short *) result);
|
608
|
+
|
609
|
+
case NATIVE_INT32:
|
610
|
+
return INT2NUM(*(signed int *) result);
|
611
|
+
|
612
|
+
case NATIVE_UINT8:
|
613
|
+
return UINT2NUM(*(unsigned char *) result);
|
614
|
+
|
615
|
+
case NATIVE_UINT16:
|
616
|
+
return UINT2NUM(*(unsigned short *) result);
|
617
|
+
|
618
|
+
case NATIVE_UINT32:
|
619
|
+
return UINT2NUM(*(unsigned int *) result);
|
620
|
+
|
621
|
+
#ifdef __x86_64__
|
622
|
+
case NATIVE_INT64:
|
623
|
+
return LL2NUM(*(signed long long *) result);
|
624
|
+
|
625
|
+
case NATIVE_UINT64:
|
626
|
+
return ULL2NUM(*(unsigned long long *) result);
|
627
|
+
#endif /* __x86_64__ */
|
628
|
+
|
629
|
+
case NATIVE_STRING:
|
630
|
+
return *(void **) result != 0 ? rb_tainted_str_new2(*(char **) result) : Qnil;
|
631
|
+
|
632
|
+
case NATIVE_POINTER:
|
633
|
+
return rbffi_Pointer_NewInstance(*(void **) result);
|
634
|
+
|
635
|
+
case NATIVE_BOOL:
|
636
|
+
return *(char *) result != 0 ? Qtrue : Qfalse;
|
637
|
+
|
638
|
+
default:
|
639
|
+
rb_raise(rb_eRuntimeError, "invalid return type: %d", fnInfo->returnType->nativeType);
|
640
|
+
return Qnil;
|
641
|
+
}
|
642
|
+
}
|
643
|
+
|
644
|
+
static VALUE
|
645
|
+
rbffi_InvokeVrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
646
|
+
{
|
647
|
+
L (*fn)(void) = (L (*)(void)) function;
|
648
|
+
L result;
|
649
|
+
|
650
|
+
checkArity(argc, 0);
|
651
|
+
|
652
|
+
result = (*fn)();
|
653
|
+
|
654
|
+
return returnL(fnInfo, &result);
|
655
|
+
}
|
656
|
+
|
657
|
+
static bool
|
658
|
+
checkArgs(int argc, VALUE* argv, FunctionType* fnInfo)
|
659
|
+
{
|
660
|
+
int i;
|
661
|
+
|
662
|
+
checkArity(argc, fnInfo->parameterCount);
|
663
|
+
for (i = 0; i < fnInfo->parameterCount; ++i) {
|
664
|
+
if (unlikely(!isLongValue(argv[i]))) {
|
665
|
+
return false;
|
666
|
+
}
|
667
|
+
}
|
668
|
+
|
669
|
+
return true;
|
670
|
+
}
|
671
|
+
|
672
|
+
#define LARG(fnInfo, argv, i) \
|
673
|
+
rbffi_GetLongValue(i, argv, fnInfo)
|
674
|
+
|
675
|
+
#define LCALL(fnInfo, argc, argv, fn, a...) ({ \
|
676
|
+
L result; \
|
677
|
+
\
|
678
|
+
if (unlikely(!checkArgs(argc, argv, fnInfo))) { \
|
679
|
+
return rbffi_CallFunction(argc, argv, function, fnInfo); \
|
680
|
+
} \
|
681
|
+
\
|
682
|
+
result = (*(fn))(a); \
|
683
|
+
\
|
684
|
+
returnL(fnInfo, &result); \
|
685
|
+
})
|
686
|
+
|
687
|
+
static VALUE
|
688
|
+
rbffi_InvokeLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
689
|
+
{
|
690
|
+
L (*fn)(L) = (L (*)(L)) function;
|
691
|
+
L result;
|
692
|
+
|
693
|
+
checkArity(argc, 1);
|
694
|
+
|
695
|
+
if (unlikely(!isLongValue(argv[0]))) {
|
696
|
+
return rbffi_CallFunction(argc, argv, function, fnInfo);
|
697
|
+
}
|
698
|
+
|
699
|
+
result = (*fn)(LARG(fnInfo, argv, 0));
|
700
|
+
|
701
|
+
return returnL(fnInfo, &result);
|
702
|
+
}
|
703
|
+
|
704
|
+
static VALUE
|
705
|
+
rbffi_InvokeLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
706
|
+
{
|
707
|
+
L (*fn)(L, L) = (L (*)(L, L)) function;
|
708
|
+
L result;
|
709
|
+
|
710
|
+
checkArity(argc, 2);
|
711
|
+
|
712
|
+
if (unlikely(!isLongValue(argv[0])) || unlikely(!isLongValue(argv[1]))) {
|
713
|
+
return rbffi_CallFunction(argc, argv, function, fnInfo);
|
714
|
+
}
|
715
|
+
|
716
|
+
result = (*fn)(LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1));
|
717
|
+
|
718
|
+
return returnL(fnInfo, &result);
|
719
|
+
}
|
720
|
+
|
721
|
+
static VALUE
|
722
|
+
rbffi_InvokeLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
723
|
+
{
|
724
|
+
L (*fn)(L, L, L) = (L (*)(L, L, L)) function;
|
725
|
+
L result;
|
726
|
+
|
727
|
+
checkArity(argc, 3);
|
728
|
+
|
729
|
+
if (unlikely(!isLongValue(argv[0])) || unlikely(!isLongValue(argv[1])) || unlikely(!isLongValue(argv[2]))) {
|
730
|
+
return rbffi_CallFunction(argc, argv, function, fnInfo);
|
731
|
+
}
|
732
|
+
|
733
|
+
result = (*fn)(LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1), LARG(fnInfo, argv, 2));
|
734
|
+
|
735
|
+
return returnL(fnInfo, &result);
|
736
|
+
}
|
737
|
+
|
738
|
+
|
739
|
+
static VALUE
|
740
|
+
rbffi_InvokeLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
741
|
+
{
|
742
|
+
return LCALL(fnInfo, argc, argv, (L (*)(L, L, L, L)) function,
|
743
|
+
LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1),
|
744
|
+
LARG(fnInfo, argv, 2), LARG(fnInfo, argv, 3));
|
745
|
+
}
|
746
|
+
|
747
|
+
static VALUE
|
748
|
+
rbffi_InvokeLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
749
|
+
{
|
750
|
+
return LCALL(fnInfo, argc, argv, (L (*)(L, L, L, L, L)) function,
|
751
|
+
LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1), LARG(fnInfo, argv, 2),
|
752
|
+
LARG(fnInfo, argv, 3), LARG(fnInfo, argv, 4));
|
753
|
+
}
|
754
|
+
|
755
|
+
static VALUE
|
756
|
+
rbffi_InvokeLLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
757
|
+
{
|
758
|
+
return LCALL(fnInfo, argc, argv, (L (*)(L, L, L, L, L, L)) function,
|
759
|
+
LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1), LARG(fnInfo, argv, 2),
|
760
|
+
LARG(fnInfo, argv, 3), LARG(fnInfo, argv, 4), LARG(fnInfo, argv, 5));
|
761
|
+
}
|
762
|
+
|
763
|
+
static VALUE
|
764
|
+
rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
|
765
|
+
{
|
766
|
+
void **ffiValues = NULL;
|
767
|
+
FFIStorage* params = NULL;
|
768
|
+
L result;
|
769
|
+
|
770
|
+
if (fnInfo->parameterCount > 0) {
|
771
|
+
ffiValues = ALLOCA_N(void *, fnInfo->parameterCount);
|
772
|
+
params = ALLOCA_N(FFIStorage, fnInfo->parameterCount);
|
773
|
+
|
774
|
+
rbffi_SetupCallParams(argc, argv,
|
775
|
+
fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues,
|
776
|
+
fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
|
777
|
+
|
778
|
+
switch (fnInfo->parameterCount) {
|
779
|
+
case 0:
|
780
|
+
result = ((L(*)(void)) function)();
|
781
|
+
break;
|
782
|
+
|
783
|
+
case 1:
|
784
|
+
result = ((L(*)(L)) function)(*(L *) ffiValues[0]);
|
785
|
+
break;
|
786
|
+
|
787
|
+
case 2:
|
788
|
+
result = ((L(*)(L, L)) function)(*(L *) ffiValues[0],
|
789
|
+
*(L *) ffiValues[1]);
|
790
|
+
break;
|
791
|
+
|
792
|
+
case 3:
|
793
|
+
result = ((L(*)(L, L, L)) function)(*(L *) ffiValues[0],
|
794
|
+
*(L *) ffiValues[1], *(L *) ffiValues[2]);
|
795
|
+
break;
|
796
|
+
|
797
|
+
case 4:
|
798
|
+
result = ((L(*)(L, L, L, L)) function)(*(L *) ffiValues[0],
|
799
|
+
*(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3]);
|
800
|
+
break;
|
801
|
+
|
802
|
+
case 5:
|
803
|
+
result = ((L(*)(L, L, L, L, L)) function)(*(L *) ffiValues[0],
|
804
|
+
*(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3],
|
805
|
+
*(L *) ffiValues[4]);
|
806
|
+
break;
|
807
|
+
|
808
|
+
case 6:
|
809
|
+
result = ((L(*)(L, L, L, L, L, L)) function)(*(L *) ffiValues[0],
|
810
|
+
*(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3],
|
811
|
+
*(L *) ffiValues[4], *(L *) ffiValues[5]);
|
812
|
+
break;
|
813
|
+
|
814
|
+
default:
|
815
|
+
rb_raise(rb_eRuntimeError, "BUG: should not reach this point");
|
816
|
+
return Qnil;
|
817
|
+
}
|
818
|
+
}
|
819
|
+
|
820
|
+
return returnL(fnInfo, &result);
|
821
|
+
}
|
822
|
+
|
823
|
+
#endif /* BYPASS_FFI */
|
824
|
+
|
825
|
+
static void*
|
826
|
+
callback_param(VALUE proc, VALUE cbInfo)
|
827
|
+
{
|
828
|
+
VALUE callback ;
|
829
|
+
if (proc == Qnil) {
|
830
|
+
return NULL ;
|
831
|
+
}
|
832
|
+
|
833
|
+
// Handle Function pointers here
|
834
|
+
if (rb_obj_is_kind_of(proc, rbffi_FunctionClass)) {
|
835
|
+
AbstractMemory* ptr;
|
836
|
+
Data_Get_Struct(proc, AbstractMemory, ptr);
|
837
|
+
return ptr->address;
|
838
|
+
}
|
839
|
+
|
840
|
+
//callback = rbffi_NativeCallback_ForProc(proc, cbInfo);
|
841
|
+
callback = rbffi_Function_ForProc(cbInfo, proc);
|
842
|
+
|
843
|
+
return ((AbstractMemory *) DATA_PTR(callback))->address;
|
844
|
+
}
|
845
|
+
|
846
|
+
|
847
|
+
void
|
848
|
+
rbffi_Call_Init(VALUE moduleFFI)
|
849
|
+
{
|
850
|
+
id_to_ptr = rb_intern("to_ptr");
|
851
|
+
id_map_symbol = rb_intern("__map_symbol");
|
852
|
+
}
|
853
|
+
|