ffi 0.4.0-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/LICENSE +51 -0
- data/README.rdoc +69 -0
- data/Rakefile +142 -0
- data/ext/ffi_c/AbstractMemory.c +412 -0
- data/ext/ffi_c/AbstractMemory.h +68 -0
- data/ext/ffi_c/AutoPointer.c +60 -0
- data/ext/ffi_c/AutoPointer.h +18 -0
- data/ext/ffi_c/Buffer.c +171 -0
- data/ext/ffi_c/Callback.c +374 -0
- data/ext/ffi_c/Callback.h +47 -0
- data/ext/ffi_c/DynamicLibrary.c +213 -0
- data/ext/ffi_c/DynamicLibrary.h +22 -0
- data/ext/ffi_c/Invoker.c +962 -0
- data/ext/ffi_c/LastError.c +135 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +156 -0
- data/ext/ffi_c/MemoryPointer.h +20 -0
- data/ext/ffi_c/NullPointer.c +143 -0
- data/ext/ffi_c/Platform.c +59 -0
- data/ext/ffi_c/Platform.h +16 -0
- data/ext/ffi_c/Pointer.c +164 -0
- data/ext/ffi_c/Pointer.h +25 -0
- data/ext/ffi_c/Struct.c +477 -0
- data/ext/ffi_c/Struct.h +26 -0
- data/ext/ffi_c/Type.c +230 -0
- data/ext/ffi_c/Type.h +28 -0
- data/ext/ffi_c/Types.c +118 -0
- data/ext/ffi_c/Types.h +54 -0
- data/ext/ffi_c/compat.h +22 -0
- data/ext/ffi_c/endian.h +40 -0
- data/ext/ffi_c/extconf.rb +31 -0
- data/ext/ffi_c/ffi.c +76 -0
- data/ext/ffi_c/libffi.bsd.mk +34 -0
- data/ext/ffi_c/libffi.darwin.mk +75 -0
- data/ext/ffi_c/libffi.gnu.mk +29 -0
- data/ext/ffi_c/libffi.mk +13 -0
- data/ext/ffi_c/libffi/ChangeLog +3243 -0
- data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
- data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
- data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
- data/ext/ffi_c/libffi/LICENSE +21 -0
- data/ext/ffi_c/libffi/Makefile.am +177 -0
- data/ext/ffi_c/libffi/Makefile.in +1640 -0
- data/ext/ffi_c/libffi/README +328 -0
- data/ext/ffi_c/libffi/TODO +1 -0
- data/ext/ffi_c/libffi/acinclude.m4 +92 -0
- data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
- data/ext/ffi_c/libffi/compile +142 -0
- data/ext/ffi_c/libffi/config.guess +1516 -0
- data/ext/ffi_c/libffi/config.sub +1626 -0
- data/ext/ffi_c/libffi/configure +24414 -0
- data/ext/ffi_c/libffi/configure.ac +365 -0
- data/ext/ffi_c/libffi/configure.host +11 -0
- data/ext/ffi_c/libffi/depcomp +584 -0
- data/ext/ffi_c/libffi/doc/libffi.info +533 -0
- data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
- data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
- data/ext/ffi_c/libffi/doc/version.texi +4 -0
- data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
- data/ext/ffi_c/libffi/include/Makefile.am +9 -0
- data/ext/ffi_c/libffi/include/Makefile.in +422 -0
- data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
- data/ext/ffi_c/libffi/install-sh +323 -0
- data/ext/ffi_c/libffi/libffi.pc.in +10 -0
- data/ext/ffi_c/libffi/libtool-version +29 -0
- data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
- data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
- data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
- data/ext/ffi_c/libffi/ltconfig +2862 -0
- data/ext/ffi_c/libffi/ltmain.sh +6930 -0
- data/ext/ffi_c/libffi/man/Makefile.am +8 -0
- data/ext/ffi_c/libffi/man/Makefile.in +395 -0
- data/ext/ffi_c/libffi/man/ffi.3 +31 -0
- data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
- data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
- data/ext/ffi_c/libffi/mdate-sh +201 -0
- data/ext/ffi_c/libffi/missing +353 -0
- data/ext/ffi_c/libffi/mkinstalldirs +158 -0
- data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
- data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
- data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
- data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
- data/ext/ffi_c/libffi/src/closures.c +596 -0
- data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
- data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
- data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
- data/ext/ffi_c/libffi/src/debug.c +59 -0
- data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
- data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
- data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
- data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
- data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
- data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
- data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
- data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
- data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
- data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
- data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
- data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
- data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
- data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
- data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
- data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
- data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
- data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
- data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
- data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
- data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
- data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
- data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
- data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
- data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
- data/ext/ffi_c/libffi/src/raw_api.c +254 -0
- data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
- data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
- data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
- data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
- data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
- data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
- data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
- data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
- data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
- data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
- data/ext/ffi_c/libffi/src/types.c +77 -0
- data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
- data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
- data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
- data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
- data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
- data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
- data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
- data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
- data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
- data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
- data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
- data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
- data/ext/ffi_c/libffi/texinfo.tex +7482 -0
- data/ext/ffi_c/rbffi.h +23 -0
- data/gen/Rakefile +12 -0
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
- data/lib/ffi.rb +11 -0
- data/lib/ffi/autopointer.rb +61 -0
- data/lib/ffi/buffer.rb +0 -0
- data/lib/ffi/callback.rb +10 -0
- data/lib/ffi/enum.rb +78 -0
- data/lib/ffi/errno.rb +8 -0
- data/lib/ffi/ffi.rb +96 -0
- data/lib/ffi/io.rb +21 -0
- data/lib/ffi/library.rb +243 -0
- data/lib/ffi/managedstruct.rb +55 -0
- data/lib/ffi/memorypointer.rb +73 -0
- data/lib/ffi/platform.rb +78 -0
- data/lib/ffi/pointer.rb +119 -0
- data/lib/ffi/struct.rb +354 -0
- data/lib/ffi/tools/const_generator.rb +177 -0
- data/lib/ffi/tools/generator.rb +58 -0
- data/lib/ffi/tools/generator_task.rb +35 -0
- data/lib/ffi/tools/struct_generator.rb +194 -0
- data/lib/ffi/tools/types_generator.rb +123 -0
- data/lib/ffi/types.rb +153 -0
- data/lib/ffi/union.rb +17 -0
- data/lib/ffi/variadic.rb +30 -0
- data/spec/ffi/bool_spec.rb +24 -0
- data/spec/ffi/buffer_spec.rb +196 -0
- data/spec/ffi/callback_spec.rb +560 -0
- data/spec/ffi/enum_spec.rb +164 -0
- data/spec/ffi/errno_spec.rb +13 -0
- data/spec/ffi/library_spec.rb +144 -0
- data/spec/ffi/managed_struct_spec.rb +56 -0
- data/spec/ffi/number_spec.rb +231 -0
- data/spec/ffi/pointer_spec.rb +195 -0
- data/spec/ffi/rbx/attach_function_spec.rb +27 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
- data/spec/ffi/rbx/spec_helper.rb +1 -0
- data/spec/ffi/rbx/struct_spec.rb +13 -0
- data/spec/ffi/spec_helper.rb +17 -0
- data/spec/ffi/string_spec.rb +103 -0
- data/spec/ffi/struct_callback_spec.rb +41 -0
- data/spec/ffi/struct_initialize_spec.rb +30 -0
- data/spec/ffi/struct_spec.rb +476 -0
- data/spec/ffi/typedef_spec.rb +48 -0
- data/spec/ffi/union_spec.rb +60 -0
- data/spec/ffi/variadic_spec.rb +84 -0
- data/spec/spec.opts +4 -0
- metadata +375 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
#ifndef _ABSTRACTMEMORY_H
|
2
|
+
#define _ABSTRACTMEMORY_H
|
3
|
+
|
4
|
+
#include <sys/param.h>
|
5
|
+
#include <sys/types.h>
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
#include "compat.h"
|
9
|
+
|
10
|
+
#ifdef __cplusplus
|
11
|
+
extern "C" {
|
12
|
+
#endif
|
13
|
+
|
14
|
+
typedef struct AbstractMemory_ AbstractMemory;
|
15
|
+
|
16
|
+
typedef struct {
|
17
|
+
VALUE (*get)(AbstractMemory* ptr, long offset);
|
18
|
+
void (*put)(AbstractMemory* ptr, long offset, VALUE value);
|
19
|
+
} MemoryOp;
|
20
|
+
|
21
|
+
typedef struct {
|
22
|
+
MemoryOp* int8;
|
23
|
+
MemoryOp* uint8;
|
24
|
+
MemoryOp* int16;
|
25
|
+
MemoryOp* uint16;
|
26
|
+
MemoryOp* int32;
|
27
|
+
MemoryOp* uint32;
|
28
|
+
MemoryOp* int64;
|
29
|
+
MemoryOp* uint64;
|
30
|
+
MemoryOp* float32;
|
31
|
+
MemoryOp* float64;
|
32
|
+
MemoryOp* pointer;
|
33
|
+
MemoryOp* strptr;
|
34
|
+
} MemoryOps;
|
35
|
+
|
36
|
+
struct AbstractMemory_ {
|
37
|
+
char* address; // Use char* instead of void* to ensure adding to it works correctly
|
38
|
+
long size;
|
39
|
+
MemoryOps* ops;
|
40
|
+
};
|
41
|
+
|
42
|
+
|
43
|
+
static inline void
|
44
|
+
checkBounds(AbstractMemory* mem, long off, long len)
|
45
|
+
{
|
46
|
+
if ((off | len | (off + len) | (mem->size - (off + len))) < 0) {
|
47
|
+
rb_raise(rb_eIndexError, "Memory access offset=%ld size=%ld is out of bounds",
|
48
|
+
off, len);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
#define MEMORY(obj) rbffi_AbstractMemory_Cast((obj), rbffi_AbstractMemoryClass)
|
53
|
+
#define MEMORY_PTR(obj) MEMORY((obj))->address
|
54
|
+
#define MEMORY_LEN(obj) MEMORY((obj))->size
|
55
|
+
|
56
|
+
extern void rbffi_AbstractMemory_Init(VALUE ffiModule);
|
57
|
+
|
58
|
+
extern AbstractMemory* rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass);
|
59
|
+
|
60
|
+
extern VALUE rbffi_AbstractMemoryClass;
|
61
|
+
extern MemoryOps rbffi_AbstractMemoryOps;
|
62
|
+
|
63
|
+
#ifdef __cplusplus
|
64
|
+
}
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#endif /* _ABSTRACTMEMORY_H */
|
68
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
|
2
|
+
#include <stdbool.h>
|
3
|
+
#include <stdint.h>
|
4
|
+
#include <limits.h>
|
5
|
+
#include <ruby.h>
|
6
|
+
#include "rbffi.h"
|
7
|
+
#include "AbstractMemory.h"
|
8
|
+
#include "Pointer.h"
|
9
|
+
#include "AutoPointer.h"
|
10
|
+
|
11
|
+
typedef struct AutoPointer {
|
12
|
+
AbstractMemory memory;
|
13
|
+
VALUE parent;
|
14
|
+
} AutoPointer;
|
15
|
+
|
16
|
+
static void autoptr_mark(AutoPointer* ptr);
|
17
|
+
static VALUE autoptr_allocate(VALUE klass);
|
18
|
+
static VALUE autoptr_set_parent(VALUE self, VALUE parent);
|
19
|
+
|
20
|
+
VALUE rbffi_AutoPointerClass = Qnil;
|
21
|
+
|
22
|
+
static VALUE
|
23
|
+
autoptr_allocate(VALUE klass)
|
24
|
+
{
|
25
|
+
AutoPointer* p;
|
26
|
+
VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, -1, p);
|
27
|
+
p->parent = Qnil;
|
28
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
29
|
+
|
30
|
+
return obj;
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE
|
34
|
+
autoptr_set_parent(VALUE self, VALUE parent)
|
35
|
+
{
|
36
|
+
AutoPointer* p;
|
37
|
+
AbstractMemory* ptr = rbffi_AbstractMemory_Cast(parent, rbffi_PointerClass);
|
38
|
+
|
39
|
+
Data_Get_Struct(self, AutoPointer, p);
|
40
|
+
p->memory = *ptr;
|
41
|
+
p->parent = parent;
|
42
|
+
|
43
|
+
return self;
|
44
|
+
}
|
45
|
+
|
46
|
+
static void
|
47
|
+
autoptr_mark(AutoPointer* ptr)
|
48
|
+
{
|
49
|
+
rb_gc_mark(ptr->parent);
|
50
|
+
}
|
51
|
+
|
52
|
+
void
|
53
|
+
rbffi_AutoPointer_Init(VALUE moduleFFI)
|
54
|
+
{
|
55
|
+
rbffi_AutoPointerClass = rb_define_class_under(moduleFFI, "AutoPointer", rbffi_PointerClass);
|
56
|
+
rb_global_variable(&rbffi_AutoPointerClass);
|
57
|
+
|
58
|
+
rb_define_alloc_func(rbffi_AutoPointerClass, autoptr_allocate);
|
59
|
+
rb_define_protected_method(rbffi_AutoPointerClass, "parent=", autoptr_set_parent, 1);
|
60
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
#ifndef _AUTOPOINTER_H
|
3
|
+
#define _AUTOPOINTER_H
|
4
|
+
|
5
|
+
#ifdef __cplusplus
|
6
|
+
extern "C" {
|
7
|
+
#endif
|
8
|
+
|
9
|
+
extern void rbffi_AutoPointer_Init(VALUE ffiModule);
|
10
|
+
extern VALUE rbffi_AutoPointerClass;
|
11
|
+
|
12
|
+
|
13
|
+
#ifdef __cplusplus
|
14
|
+
}
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#endif /* _AUTOPOINTER_H */
|
18
|
+
|
data/ext/ffi_c/Buffer.c
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
#include <stdbool.h>
|
2
|
+
#include <stdint.h>
|
3
|
+
#include <limits.h>
|
4
|
+
#include <ruby.h>
|
5
|
+
#include "rbffi.h"
|
6
|
+
#include "AbstractMemory.h"
|
7
|
+
|
8
|
+
typedef struct Buffer {
|
9
|
+
AbstractMemory memory;
|
10
|
+
char* storage; /* start of malloc area */
|
11
|
+
int type_size;
|
12
|
+
VALUE parent;
|
13
|
+
} Buffer;
|
14
|
+
|
15
|
+
static VALUE buffer_allocate(VALUE klass);
|
16
|
+
static VALUE buffer_initialize(int argc, VALUE* argv, VALUE self);
|
17
|
+
static void buffer_release(Buffer* ptr);
|
18
|
+
static void buffer_mark(Buffer* ptr);
|
19
|
+
static VALUE buffer_free(VALUE self);
|
20
|
+
|
21
|
+
static VALUE BufferClass = Qnil;
|
22
|
+
#define BUFFER(obj) ((Buffer *) rbffi_AbstractMemory_Cast((obj), BufferClass))
|
23
|
+
|
24
|
+
static VALUE
|
25
|
+
buffer_allocate(VALUE klass)
|
26
|
+
{
|
27
|
+
Buffer* buffer;
|
28
|
+
VALUE obj;
|
29
|
+
|
30
|
+
obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
|
31
|
+
buffer->parent = Qnil;
|
32
|
+
buffer->memory.ops = &rbffi_AbstractMemoryOps;
|
33
|
+
|
34
|
+
return obj;
|
35
|
+
}
|
36
|
+
|
37
|
+
static void
|
38
|
+
buffer_release(Buffer* ptr)
|
39
|
+
{
|
40
|
+
if (ptr->storage != NULL) {
|
41
|
+
free(ptr->storage);
|
42
|
+
ptr->storage = NULL;
|
43
|
+
}
|
44
|
+
|
45
|
+
xfree(ptr);
|
46
|
+
}
|
47
|
+
|
48
|
+
static VALUE
|
49
|
+
buffer_initialize(int argc, VALUE* argv, VALUE self)
|
50
|
+
{
|
51
|
+
VALUE size = Qnil, count = Qnil, clear = Qnil;
|
52
|
+
Buffer* p;
|
53
|
+
int nargs;
|
54
|
+
|
55
|
+
Data_Get_Struct(self, Buffer, p);
|
56
|
+
|
57
|
+
nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
|
58
|
+
p->type_size = rbffi_type_size(size);
|
59
|
+
p->memory.size = p->type_size * (nargs > 1 ? NUM2LONG(count) : 1);
|
60
|
+
|
61
|
+
p->storage = malloc(p->memory.size + 7);
|
62
|
+
if (p->storage == NULL) {
|
63
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", p->memory.size);
|
64
|
+
}
|
65
|
+
|
66
|
+
/* ensure the memory is aligned on at least a 8 byte boundary */
|
67
|
+
p->memory.address = (void *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);
|
68
|
+
|
69
|
+
if (nargs > 2 && (RTEST(clear) || clear == Qnil) && p->memory.size > 0) {
|
70
|
+
memset(p->memory.address, 0, p->memory.size);
|
71
|
+
}
|
72
|
+
|
73
|
+
if (rb_block_given_p()) {
|
74
|
+
return rb_ensure(rb_yield, self, buffer_free, self);
|
75
|
+
}
|
76
|
+
|
77
|
+
return self;
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE
|
81
|
+
buffer_alloc_inout(int argc, VALUE* argv, VALUE klass)
|
82
|
+
{
|
83
|
+
return buffer_initialize(argc, argv, buffer_allocate(klass));
|
84
|
+
}
|
85
|
+
|
86
|
+
static VALUE
|
87
|
+
buffer_plus(VALUE self, VALUE offset)
|
88
|
+
{
|
89
|
+
Buffer* ptr = BUFFER(self);
|
90
|
+
Buffer* p;
|
91
|
+
VALUE retval;
|
92
|
+
long off = NUM2LONG(offset);
|
93
|
+
|
94
|
+
checkBounds(&ptr->memory, off, 1);
|
95
|
+
|
96
|
+
retval = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, p);
|
97
|
+
p->memory.address = ptr->memory.address + off;
|
98
|
+
p->memory.size = ptr->memory.size - off;
|
99
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
100
|
+
p->parent = self;
|
101
|
+
|
102
|
+
return retval;
|
103
|
+
}
|
104
|
+
|
105
|
+
static VALUE
|
106
|
+
buffer_aref(VALUE self, VALUE offset)
|
107
|
+
{
|
108
|
+
Buffer* ptr;
|
109
|
+
|
110
|
+
Data_Get_Struct(self, Buffer, ptr);
|
111
|
+
return buffer_plus(self, INT2FIX(ptr->type_size * NUM2INT(offset)));
|
112
|
+
}
|
113
|
+
|
114
|
+
static VALUE
|
115
|
+
buffer_type_size(VALUE self)
|
116
|
+
{
|
117
|
+
Buffer* ptr;
|
118
|
+
|
119
|
+
Data_Get_Struct(self, Buffer, ptr);
|
120
|
+
return INT2NUM(ptr->type_size);
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE
|
124
|
+
buffer_inspect(VALUE self)
|
125
|
+
{
|
126
|
+
char tmp[100];
|
127
|
+
|
128
|
+
snprintf(tmp, sizeof(tmp), "#<Buffer size=%ld>", BUFFER(self)->memory.size);
|
129
|
+
|
130
|
+
return rb_str_new2(tmp);
|
131
|
+
}
|
132
|
+
|
133
|
+
/* Only used to free the buffer if the yield in the initializer throws an exception */
|
134
|
+
static VALUE
|
135
|
+
buffer_free(VALUE self)
|
136
|
+
{
|
137
|
+
Buffer* ptr;
|
138
|
+
|
139
|
+
Data_Get_Struct(self, Buffer, ptr);
|
140
|
+
if (ptr->storage != NULL) {
|
141
|
+
free(ptr->storage);
|
142
|
+
ptr->storage = NULL;
|
143
|
+
}
|
144
|
+
|
145
|
+
return self;
|
146
|
+
}
|
147
|
+
|
148
|
+
static void
|
149
|
+
buffer_mark(Buffer* ptr)
|
150
|
+
{
|
151
|
+
rb_gc_mark(ptr->parent);
|
152
|
+
}
|
153
|
+
|
154
|
+
void
|
155
|
+
rbffi_Buffer_Init(VALUE moduleFFI)
|
156
|
+
{
|
157
|
+
BufferClass = rb_define_class_under(moduleFFI, "Buffer", rbffi_AbstractMemoryClass);
|
158
|
+
|
159
|
+
rb_global_variable(&BufferClass);
|
160
|
+
rb_define_alloc_func(BufferClass, buffer_allocate);
|
161
|
+
|
162
|
+
rb_define_singleton_method(BufferClass, "alloc_inout", buffer_alloc_inout, -1);
|
163
|
+
rb_define_singleton_method(BufferClass, "alloc_out", buffer_alloc_inout, -1);
|
164
|
+
rb_define_singleton_method(BufferClass, "alloc_in", buffer_alloc_inout, -1);
|
165
|
+
|
166
|
+
rb_define_method(BufferClass, "initialize", buffer_initialize, -1);
|
167
|
+
rb_define_method(BufferClass, "inspect", buffer_inspect, 0);
|
168
|
+
rb_define_method(BufferClass, "type_size", buffer_type_size, 0);
|
169
|
+
rb_define_method(BufferClass, "[]", buffer_aref, 1);
|
170
|
+
rb_define_method(BufferClass, "+", buffer_plus, 1);
|
171
|
+
}
|
@@ -0,0 +1,374 @@
|
|
1
|
+
#include <sys/param.h>
|
2
|
+
#include <sys/types.h>
|
3
|
+
#ifndef _WIN32
|
4
|
+
# include <sys/mman.h>
|
5
|
+
#endif
|
6
|
+
#include <ruby.h>
|
7
|
+
#include <ffi.h>
|
8
|
+
#include "AbstractMemory.h"
|
9
|
+
#include "Pointer.h"
|
10
|
+
#include "MemoryPointer.h"
|
11
|
+
#include "Callback.h"
|
12
|
+
#include "Types.h"
|
13
|
+
#include "Type.h"
|
14
|
+
#include "rbffi.h"
|
15
|
+
#include "compat.h"
|
16
|
+
#include "extconf.h"
|
17
|
+
|
18
|
+
static void cbinfo_mark(CallbackInfo* cbInfo);
|
19
|
+
static void cbinfo_free(CallbackInfo *);
|
20
|
+
|
21
|
+
#if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
|
22
|
+
static void* ffi_closure_alloc(size_t size, void** code);
|
23
|
+
static void ffi_closure_free(void* ptr);
|
24
|
+
ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
|
25
|
+
void (*fun)(ffi_cif*, void*, void**, void*),
|
26
|
+
void* user_data, void* code);
|
27
|
+
#endif /* HAVE_FFI_CLOSURE_ALLOC */
|
28
|
+
|
29
|
+
static VALUE CallbackInfoClass = Qnil;
|
30
|
+
static VALUE NativeCallbackClass = Qnil;
|
31
|
+
static ID id_call = Qnil, id_cbtable = Qnil;
|
32
|
+
|
33
|
+
VALUE rbffi_CallbackInfoClass = Qnil;
|
34
|
+
|
35
|
+
static VALUE
|
36
|
+
cbinfo_allocate(VALUE klass)
|
37
|
+
{
|
38
|
+
CallbackInfo* cbInfo;
|
39
|
+
VALUE obj = Data_Make_Struct(klass, CallbackInfo, cbinfo_mark, cbinfo_free, cbInfo);
|
40
|
+
|
41
|
+
cbInfo->type.ffiType = &ffi_type_pointer;
|
42
|
+
cbInfo->type.size = ffi_type_pointer.size;
|
43
|
+
cbInfo->type.alignment = ffi_type_pointer.alignment;
|
44
|
+
cbInfo->type.nativeType = NATIVE_CALLBACK;
|
45
|
+
cbInfo->rbReturnType = Qnil;
|
46
|
+
|
47
|
+
return obj;
|
48
|
+
}
|
49
|
+
|
50
|
+
static VALUE
|
51
|
+
cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
|
52
|
+
{
|
53
|
+
CallbackInfo *cbInfo;
|
54
|
+
int paramCount;
|
55
|
+
ffi_status status;
|
56
|
+
int i;
|
57
|
+
|
58
|
+
Check_Type(rbParamTypes, T_ARRAY);
|
59
|
+
|
60
|
+
|
61
|
+
paramCount = RARRAY_LEN(rbParamTypes);
|
62
|
+
|
63
|
+
Data_Get_Struct(self, CallbackInfo, cbInfo);
|
64
|
+
cbInfo->parameterCount = paramCount;
|
65
|
+
cbInfo->parameterTypes = xcalloc(paramCount, sizeof(*cbInfo->parameterTypes));
|
66
|
+
cbInfo->ffiParameterTypes = xcalloc(paramCount, sizeof(ffi_type *));
|
67
|
+
Data_Get_Struct(rbReturnType, Type, cbInfo->returnType);
|
68
|
+
cbInfo->rbReturnType = rbReturnType;
|
69
|
+
cbInfo->rbParameterTypes = rbParamTypes;
|
70
|
+
|
71
|
+
for (i = 0; i < paramCount; ++i) {
|
72
|
+
VALUE entry = rb_ary_entry(rbParamTypes, i);
|
73
|
+
if (!rb_obj_is_kind_of(entry, rbffi_TypeClass)) {
|
74
|
+
rb_raise(rb_eTypeError, "Invalid parameter type");
|
75
|
+
}
|
76
|
+
Data_Get_Struct(entry, Type, cbInfo->parameterTypes[i]);
|
77
|
+
cbInfo->ffiParameterTypes[i] = cbInfo->parameterTypes[i]->ffiType;
|
78
|
+
if (cbInfo->ffiParameterTypes[i] == NULL) {
|
79
|
+
rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]->nativeType);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
if (!rb_obj_is_kind_of(rbReturnType, rbffi_TypeClass)) {
|
84
|
+
rb_raise(rb_eTypeError, "Invalid return type");
|
85
|
+
}
|
86
|
+
|
87
|
+
cbInfo->ffiReturnType = cbInfo->returnType->ffiType;
|
88
|
+
if (cbInfo->ffiReturnType == NULL) {
|
89
|
+
rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType->nativeType);
|
90
|
+
}
|
91
|
+
#if defined(_WIN32) && defined(notyet)
|
92
|
+
cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
|
93
|
+
#else
|
94
|
+
cbInfo->abi = FFI_DEFAULT_ABI;
|
95
|
+
#endif
|
96
|
+
status = ffi_prep_cif(&cbInfo->ffi_cif, cbInfo->abi, cbInfo->parameterCount,
|
97
|
+
cbInfo->ffiReturnType, cbInfo->ffiParameterTypes);
|
98
|
+
switch (status) {
|
99
|
+
case FFI_BAD_ABI:
|
100
|
+
rb_raise(rb_eArgError, "Invalid ABI specified");
|
101
|
+
case FFI_BAD_TYPEDEF:
|
102
|
+
rb_raise(rb_eArgError, "Invalid argument type specified");
|
103
|
+
case FFI_OK:
|
104
|
+
break;
|
105
|
+
default:
|
106
|
+
rb_raise(rb_eArgError, "Unknown FFI error");
|
107
|
+
}
|
108
|
+
return self;
|
109
|
+
}
|
110
|
+
|
111
|
+
static void
|
112
|
+
cbinfo_mark(CallbackInfo* cbInfo)
|
113
|
+
{
|
114
|
+
rb_gc_mark(cbInfo->rbReturnType);
|
115
|
+
rb_gc_mark(cbInfo->rbParameterTypes);
|
116
|
+
}
|
117
|
+
|
118
|
+
static void
|
119
|
+
cbinfo_free(CallbackInfo* cbInfo)
|
120
|
+
{
|
121
|
+
if (cbInfo->parameterTypes != NULL) {
|
122
|
+
xfree(cbInfo->parameterTypes);
|
123
|
+
}
|
124
|
+
if (cbInfo->ffiParameterTypes != NULL) {
|
125
|
+
xfree(cbInfo->ffiParameterTypes);
|
126
|
+
}
|
127
|
+
xfree(cbInfo);
|
128
|
+
}
|
129
|
+
|
130
|
+
static void
|
131
|
+
native_callback_free(NativeCallback* cb)
|
132
|
+
{
|
133
|
+
if (cb->ffi_closure != NULL) {
|
134
|
+
ffi_closure_free(cb->ffi_closure);
|
135
|
+
}
|
136
|
+
xfree(cb);
|
137
|
+
}
|
138
|
+
|
139
|
+
static void
|
140
|
+
native_callback_mark(NativeCallback* cb)
|
141
|
+
{
|
142
|
+
rb_gc_mark(cb->rbCallbackInfo);
|
143
|
+
rb_gc_mark(cb->rbProc);
|
144
|
+
}
|
145
|
+
|
146
|
+
static void
|
147
|
+
native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
148
|
+
{
|
149
|
+
NativeCallback* cb = (NativeCallback *) user_data;
|
150
|
+
CallbackInfo *cbInfo = cb->cbInfo;
|
151
|
+
VALUE* rbParams;
|
152
|
+
VALUE rbReturnValue;
|
153
|
+
int i;
|
154
|
+
|
155
|
+
rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
|
156
|
+
for (i = 0; i < cbInfo->parameterCount; ++i) {
|
157
|
+
VALUE param;
|
158
|
+
switch (cbInfo->parameterTypes[i]->nativeType) {
|
159
|
+
case NATIVE_INT8:
|
160
|
+
param = INT2NUM(*(int8_t *) parameters[i]);
|
161
|
+
break;
|
162
|
+
case NATIVE_UINT8:
|
163
|
+
param = UINT2NUM(*(uint8_t *) parameters[i]);
|
164
|
+
break;
|
165
|
+
case NATIVE_INT16:
|
166
|
+
param = INT2NUM(*(int16_t *) parameters[i]);
|
167
|
+
break;
|
168
|
+
case NATIVE_UINT16:
|
169
|
+
param = UINT2NUM(*(uint16_t *) parameters[i]);
|
170
|
+
break;
|
171
|
+
case NATIVE_INT32:
|
172
|
+
param = INT2NUM(*(int32_t *) parameters[i]);
|
173
|
+
break;
|
174
|
+
case NATIVE_UINT32:
|
175
|
+
param = UINT2NUM(*(uint32_t *) parameters[i]);
|
176
|
+
break;
|
177
|
+
case NATIVE_INT64:
|
178
|
+
param = LL2NUM(*(int64_t *) parameters[i]);
|
179
|
+
break;
|
180
|
+
case NATIVE_UINT64:
|
181
|
+
param = ULL2NUM(*(uint64_t *) parameters[i]);
|
182
|
+
break;
|
183
|
+
case NATIVE_FLOAT32:
|
184
|
+
param = rb_float_new(*(float *) parameters[i]);
|
185
|
+
break;
|
186
|
+
case NATIVE_FLOAT64:
|
187
|
+
param = rb_float_new(*(double *) parameters[i]);
|
188
|
+
break;
|
189
|
+
case NATIVE_STRING:
|
190
|
+
param = rb_tainted_str_new2(*(char **) parameters[i]);
|
191
|
+
break;
|
192
|
+
case NATIVE_POINTER:
|
193
|
+
param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
|
194
|
+
break;
|
195
|
+
case NATIVE_BOOL:
|
196
|
+
param = (*(void **) parameters[i]) ? Qtrue : Qfalse;
|
197
|
+
break;
|
198
|
+
case NATIVE_CALLBACK:
|
199
|
+
param = rbffi_NativeValue_ToRuby(cbInfo->parameterTypes[i],
|
200
|
+
rb_ary_entry(cbInfo->rbParameterTypes, i), parameters[i], Qnil);
|
201
|
+
break;
|
202
|
+
default:
|
203
|
+
param = Qnil;
|
204
|
+
break;
|
205
|
+
}
|
206
|
+
rbParams[i] = param;
|
207
|
+
}
|
208
|
+
rbReturnValue = rb_funcall2(cb->rbProc, id_call, cbInfo->parameterCount, rbParams);
|
209
|
+
if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
|
210
|
+
memset(retval, 0, cbInfo->ffiReturnType->size);
|
211
|
+
} else switch (cbInfo->returnType->nativeType) {
|
212
|
+
case NATIVE_INT8:
|
213
|
+
case NATIVE_INT16:
|
214
|
+
case NATIVE_INT32:
|
215
|
+
*((ffi_sarg *) retval) = NUM2INT(rbReturnValue);
|
216
|
+
break;
|
217
|
+
case NATIVE_UINT8:
|
218
|
+
case NATIVE_UINT16:
|
219
|
+
case NATIVE_UINT32:
|
220
|
+
*((ffi_arg *) retval) = NUM2UINT(rbReturnValue);
|
221
|
+
break;
|
222
|
+
case NATIVE_INT64:
|
223
|
+
*((int64_t *) retval) = NUM2LL(rbReturnValue);
|
224
|
+
break;
|
225
|
+
case NATIVE_UINT64:
|
226
|
+
*((uint64_t *) retval) = NUM2ULL(rbReturnValue);
|
227
|
+
break;
|
228
|
+
case NATIVE_FLOAT32:
|
229
|
+
*((float *) retval) = (float) NUM2DBL(rbReturnValue);
|
230
|
+
break;
|
231
|
+
case NATIVE_FLOAT64:
|
232
|
+
*((double *) retval) = NUM2DBL(rbReturnValue);
|
233
|
+
break;
|
234
|
+
case NATIVE_POINTER:
|
235
|
+
if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
|
236
|
+
*((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
|
237
|
+
} else {
|
238
|
+
// Default to returning NULL if not a value pointer object. handles nil case as well
|
239
|
+
*((void **) retval) = NULL;
|
240
|
+
}
|
241
|
+
break;
|
242
|
+
case NATIVE_BOOL:
|
243
|
+
*((ffi_sarg *) retval) = TYPE(rbReturnValue) == T_TRUE ? 1 : 0;
|
244
|
+
break;
|
245
|
+
case NATIVE_CALLBACK:
|
246
|
+
if (rb_obj_is_kind_of(rbReturnValue, rb_cProc) || rb_respond_to(rbReturnValue, id_call)) {
|
247
|
+
VALUE callback;
|
248
|
+
|
249
|
+
callback = rbffi_NativeCallback_ForProc(rbReturnValue, cbInfo->rbReturnType);
|
250
|
+
|
251
|
+
*((void **) retval) = ((NativeCallback *) DATA_PTR(callback))->code;
|
252
|
+
} else {
|
253
|
+
*((void **) retval) = NULL;
|
254
|
+
}
|
255
|
+
break;
|
256
|
+
|
257
|
+
default:
|
258
|
+
*((ffi_arg *) retval) = 0;
|
259
|
+
break;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
|
263
|
+
static VALUE
|
264
|
+
native_callback_allocate(VALUE klass)
|
265
|
+
{
|
266
|
+
NativeCallback* closure;
|
267
|
+
VALUE obj;
|
268
|
+
|
269
|
+
obj = Data_Make_Struct(klass, NativeCallback, native_callback_mark, native_callback_free, closure);
|
270
|
+
closure->rbCallbackInfo = Qnil;
|
271
|
+
closure->rbProc = Qnil;
|
272
|
+
|
273
|
+
return obj;
|
274
|
+
}
|
275
|
+
|
276
|
+
VALUE
|
277
|
+
rbffi_NativeCallback_NewInstance(VALUE rbCallbackInfo, VALUE rbProc)
|
278
|
+
{
|
279
|
+
NativeCallback* closure = NULL;
|
280
|
+
CallbackInfo* cbInfo;
|
281
|
+
VALUE obj;
|
282
|
+
ffi_status status;
|
283
|
+
|
284
|
+
Data_Get_Struct(rbCallbackInfo, CallbackInfo, cbInfo);
|
285
|
+
obj = Data_Make_Struct(NativeCallbackClass, NativeCallback, native_callback_mark, native_callback_free, closure);
|
286
|
+
closure->cbInfo = cbInfo;
|
287
|
+
closure->rbProc = rbProc;
|
288
|
+
closure->rbCallbackInfo = rbCallbackInfo;
|
289
|
+
|
290
|
+
closure->ffi_closure = ffi_closure_alloc(sizeof(*closure->ffi_closure), &closure->code);
|
291
|
+
if (closure->ffi_closure == NULL) {
|
292
|
+
rb_raise(rb_eNoMemError, "Failed to allocate FFI native closure");
|
293
|
+
}
|
294
|
+
|
295
|
+
status = ffi_prep_closure_loc(closure->ffi_closure, &cbInfo->ffi_cif,
|
296
|
+
native_callback_invoke, closure, closure->code);
|
297
|
+
if (status != FFI_OK) {
|
298
|
+
rb_raise(rb_eArgError, "ffi_prep_closure_loc failed");
|
299
|
+
}
|
300
|
+
|
301
|
+
return obj;
|
302
|
+
}
|
303
|
+
|
304
|
+
VALUE
|
305
|
+
rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo)
|
306
|
+
{
|
307
|
+
VALUE callback;
|
308
|
+
VALUE cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;
|
309
|
+
if (cbTable == Qnil) {
|
310
|
+
cbTable = rb_hash_new();
|
311
|
+
rb_ivar_set(proc, id_cbtable, cbTable);
|
312
|
+
}
|
313
|
+
callback = rb_hash_aref(cbTable, cbInfo);
|
314
|
+
if (callback != Qnil) {
|
315
|
+
return callback;
|
316
|
+
}
|
317
|
+
callback = rbffi_NativeCallback_NewInstance(cbInfo, proc);
|
318
|
+
rb_hash_aset(cbTable, cbInfo, callback);
|
319
|
+
return callback;
|
320
|
+
}
|
321
|
+
#if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
|
322
|
+
/*
|
323
|
+
* versions of ffi_closure_alloc, ffi_closure_free and ffi_prep_closure_loc for older
|
324
|
+
* system libffi versions.
|
325
|
+
*/
|
326
|
+
static void*
|
327
|
+
ffi_closure_alloc(size_t size, void** code)
|
328
|
+
{
|
329
|
+
void* closure;
|
330
|
+
closure = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
331
|
+
MAP_ANON | MAP_PRIVATE, -1, 0);
|
332
|
+
if (closure == (void *) -1) {
|
333
|
+
return NULL;
|
334
|
+
}
|
335
|
+
memset(closure, 0, size);
|
336
|
+
*code = closure;
|
337
|
+
return closure;
|
338
|
+
}
|
339
|
+
|
340
|
+
static void
|
341
|
+
ffi_closure_free(void* ptr)
|
342
|
+
{
|
343
|
+
munmap(ptr, sizeof(ffi_closure));
|
344
|
+
}
|
345
|
+
|
346
|
+
ffi_status
|
347
|
+
ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
|
348
|
+
void (*fun)(ffi_cif*, void*, void**, void*),
|
349
|
+
void* user_data, void* code)
|
350
|
+
{
|
351
|
+
ffi_status retval = ffi_prep_closure(closure, cif, fun, user_data);
|
352
|
+
if (retval == FFI_OK) {
|
353
|
+
mprotect(closure, sizeof(ffi_closure), PROT_READ | PROT_EXEC);
|
354
|
+
}
|
355
|
+
return retval;
|
356
|
+
}
|
357
|
+
|
358
|
+
#endif /* HAVE_FFI_CLOSURE_ALLOC */
|
359
|
+
|
360
|
+
void
|
361
|
+
rbffi_Callback_Init(VALUE moduleFFI)
|
362
|
+
{
|
363
|
+
rbffi_CallbackInfoClass = CallbackInfoClass = rb_define_class_under(moduleFFI, "CallbackInfo", rbffi_TypeClass);
|
364
|
+
rb_global_variable(&rbffi_CallbackInfoClass);
|
365
|
+
|
366
|
+
rb_define_alloc_func(CallbackInfoClass, cbinfo_allocate);
|
367
|
+
rb_define_method(CallbackInfoClass, "initialize", cbinfo_initialize, 2);
|
368
|
+
|
369
|
+
NativeCallbackClass = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
|
370
|
+
rb_global_variable(&NativeCallbackClass);
|
371
|
+
rb_define_alloc_func(NativeCallbackClass, native_callback_allocate);
|
372
|
+
id_call = rb_intern("call");
|
373
|
+
id_cbtable = rb_intern("@__ffi_callback_table__");
|
374
|
+
}
|