ffi 0.2.0 → 0.3.0

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.

Files changed (305) hide show
  1. data/README.rdoc +19 -0
  2. data/Rakefile +65 -55
  3. data/ext/{AbstractMemory.c → ffi_c/AbstractMemory.c} +67 -40
  4. data/ext/{AbstractMemory.h → ffi_c/AbstractMemory.h} +10 -8
  5. data/ext/{AutoPointer.c → ffi_c/AutoPointer.c} +17 -8
  6. data/ext/{AutoPointer.h → ffi_c/AutoPointer.h} +0 -0
  7. data/ext/ffi_c/Buffer.c +136 -0
  8. data/ext/{Callback.c → ffi_c/Callback.c} +60 -35
  9. data/ext/{Callback.h → ffi_c/Callback.h} +1 -7
  10. data/ext/{Invoker.c → ffi_c/Invoker.c} +472 -102
  11. data/ext/ffi_c/MemoryPointer.c +146 -0
  12. data/ext/{MemoryPointer.h → ffi_c/MemoryPointer.h} +2 -7
  13. data/ext/ffi_c/NativeLibrary.c +149 -0
  14. data/ext/{NativeLibrary.h → ffi_c/NativeLibrary.h} +0 -0
  15. data/ext/ffi_c/NullPointer.c +104 -0
  16. data/ext/{Platform.c → ffi_c/Platform.c} +0 -0
  17. data/ext/{Platform.h → ffi_c/Platform.h} +0 -7
  18. data/ext/{Pointer.c → ffi_c/Pointer.c} +35 -15
  19. data/ext/{Pointer.h → ffi_c/Pointer.h} +4 -2
  20. data/ext/ffi_c/Struct.c +542 -0
  21. data/ext/ffi_c/Struct.h +26 -0
  22. data/ext/ffi_c/Types.c +76 -0
  23. data/ext/{Types.h → ffi_c/Types.h} +23 -28
  24. data/ext/{compat.h → ffi_c/compat.h} +2 -2
  25. data/ext/{extconf.rb → ffi_c/extconf.rb} +12 -7
  26. data/ext/ffi_c/ffi.c +99 -0
  27. data/ext/ffi_c/ffi.mk +23 -0
  28. data/ext/{libffi.darwin.mk → ffi_c/libffi.darwin.mk} +0 -0
  29. data/ext/ffi_c/libffi.mk +11 -0
  30. data/ext/{libffi → ffi_c/libffi}/ChangeLog +0 -0
  31. data/ext/{libffi → ffi_c/libffi}/ChangeLog.libffi +0 -0
  32. data/ext/{libffi → ffi_c/libffi}/ChangeLog.libgcj +0 -0
  33. data/ext/{libffi → ffi_c/libffi}/ChangeLog.v1 +0 -0
  34. data/ext/{libffi → ffi_c/libffi}/LICENSE +0 -0
  35. data/ext/{libffi → ffi_c/libffi}/Makefile.am +0 -0
  36. data/ext/{libffi → ffi_c/libffi}/Makefile.in +0 -0
  37. data/ext/{libffi → ffi_c/libffi}/README +0 -0
  38. data/ext/{libffi → ffi_c/libffi}/TODO +0 -0
  39. data/ext/{libffi → ffi_c/libffi}/acinclude.m4 +0 -0
  40. data/ext/{libffi → ffi_c/libffi}/aclocal.m4 +0 -0
  41. data/ext/{libffi → ffi_c/libffi}/compile +0 -0
  42. data/ext/{libffi → ffi_c/libffi}/config.guess +0 -0
  43. data/ext/{libffi → ffi_c/libffi}/config.sub +0 -0
  44. data/ext/{libffi → ffi_c/libffi}/configure +0 -0
  45. data/ext/{libffi → ffi_c/libffi}/configure.ac +0 -0
  46. data/ext/{libffi → ffi_c/libffi}/configure.host +0 -0
  47. data/ext/{libffi → ffi_c/libffi}/depcomp +0 -0
  48. data/ext/{libffi → ffi_c/libffi}/doc/libffi.info +0 -0
  49. data/ext/{libffi → ffi_c/libffi}/doc/libffi.texi +0 -0
  50. data/ext/{libffi → ffi_c/libffi}/doc/stamp-vti +0 -0
  51. data/ext/{libffi → ffi_c/libffi}/doc/version.texi +0 -0
  52. data/ext/{libffi → ffi_c/libffi}/fficonfig.h.in +0 -0
  53. data/ext/{libffi → ffi_c/libffi}/include/Makefile.am +0 -0
  54. data/ext/{libffi → ffi_c/libffi}/include/Makefile.in +0 -0
  55. data/ext/{libffi → ffi_c/libffi}/include/ffi.h.in +0 -0
  56. data/ext/{libffi → ffi_c/libffi}/include/ffi_common.h +0 -0
  57. data/ext/{libffi → ffi_c/libffi}/install-sh +0 -0
  58. data/ext/{libffi → ffi_c/libffi}/libffi.pc.in +0 -0
  59. data/ext/{libffi → ffi_c/libffi}/libtool-version +0 -0
  60. data/ext/{libffi → ffi_c/libffi}/ltcf-c.sh +0 -0
  61. data/ext/{libffi → ffi_c/libffi}/ltcf-cxx.sh +0 -0
  62. data/ext/{libffi → ffi_c/libffi}/ltcf-gcj.sh +0 -0
  63. data/ext/{libffi → ffi_c/libffi}/ltconfig +0 -0
  64. data/ext/{libffi → ffi_c/libffi}/ltmain.sh +0 -0
  65. data/ext/{libffi → ffi_c/libffi}/man/Makefile.am +0 -0
  66. data/ext/{libffi → ffi_c/libffi}/man/Makefile.in +0 -0
  67. data/ext/{libffi → ffi_c/libffi}/man/ffi.3 +0 -0
  68. data/ext/{libffi → ffi_c/libffi}/man/ffi_call.3 +0 -0
  69. data/ext/{libffi → ffi_c/libffi}/man/ffi_prep_cif.3 +0 -0
  70. data/ext/{libffi → ffi_c/libffi}/mdate-sh +0 -0
  71. data/ext/{libffi → ffi_c/libffi}/missing +0 -0
  72. data/ext/{libffi → ffi_c/libffi}/mkinstalldirs +0 -0
  73. data/ext/{libffi → ffi_c/libffi}/src/alpha/ffi.c +0 -0
  74. data/ext/{libffi → ffi_c/libffi}/src/alpha/ffitarget.h +0 -0
  75. data/ext/{libffi → ffi_c/libffi}/src/alpha/osf.S +0 -0
  76. data/ext/{libffi → ffi_c/libffi}/src/arm/ffi.c +0 -0
  77. data/ext/{libffi → ffi_c/libffi}/src/arm/ffitarget.h +0 -0
  78. data/ext/{libffi → ffi_c/libffi}/src/arm/sysv.S +0 -0
  79. data/ext/{libffi → ffi_c/libffi}/src/closures.c +0 -0
  80. data/ext/{libffi → ffi_c/libffi}/src/cris/ffi.c +0 -0
  81. data/ext/{libffi → ffi_c/libffi}/src/cris/ffitarget.h +0 -0
  82. data/ext/{libffi → ffi_c/libffi}/src/cris/sysv.S +0 -0
  83. data/ext/{libffi → ffi_c/libffi}/src/debug.c +0 -0
  84. data/ext/{libffi → ffi_c/libffi}/src/dlmalloc.c +0 -0
  85. data/ext/{libffi → ffi_c/libffi}/src/frv/eabi.S +0 -0
  86. data/ext/{libffi → ffi_c/libffi}/src/frv/ffi.c +0 -0
  87. data/ext/{libffi → ffi_c/libffi}/src/frv/ffitarget.h +0 -0
  88. data/ext/{libffi → ffi_c/libffi}/src/ia64/ffi.c +0 -0
  89. data/ext/{libffi → ffi_c/libffi}/src/ia64/ffitarget.h +0 -0
  90. data/ext/{libffi → ffi_c/libffi}/src/ia64/ia64_flags.h +0 -0
  91. data/ext/{libffi → ffi_c/libffi}/src/ia64/unix.S +0 -0
  92. data/ext/{libffi → ffi_c/libffi}/src/java_raw_api.c +0 -0
  93. data/ext/{libffi → ffi_c/libffi}/src/m32r/ffi.c +0 -0
  94. data/ext/{libffi → ffi_c/libffi}/src/m32r/ffitarget.h +0 -0
  95. data/ext/{libffi → ffi_c/libffi}/src/m32r/sysv.S +0 -0
  96. data/ext/{libffi → ffi_c/libffi}/src/m68k/ffi.c +0 -0
  97. data/ext/{libffi → ffi_c/libffi}/src/m68k/ffitarget.h +0 -0
  98. data/ext/{libffi → ffi_c/libffi}/src/m68k/sysv.S +0 -0
  99. data/ext/{libffi → ffi_c/libffi}/src/mips/ffi.c +0 -0
  100. data/ext/{libffi → ffi_c/libffi}/src/mips/ffitarget.h +0 -0
  101. data/ext/{libffi → ffi_c/libffi}/src/mips/n32.S +0 -0
  102. data/ext/{libffi → ffi_c/libffi}/src/mips/o32.S +0 -0
  103. data/ext/{libffi → ffi_c/libffi}/src/pa/ffi.c +0 -0
  104. data/ext/{libffi → ffi_c/libffi}/src/pa/ffitarget.h +0 -0
  105. data/ext/{libffi → ffi_c/libffi}/src/pa/hpux32.S +0 -0
  106. data/ext/{libffi → ffi_c/libffi}/src/pa/linux.S +0 -0
  107. data/ext/{libffi → ffi_c/libffi}/src/powerpc/aix.S +0 -0
  108. data/ext/{libffi → ffi_c/libffi}/src/powerpc/aix_closure.S +0 -0
  109. data/ext/{libffi → ffi_c/libffi}/src/powerpc/asm.h +0 -0
  110. data/ext/{libffi → ffi_c/libffi}/src/powerpc/darwin.S +0 -0
  111. data/ext/{libffi → ffi_c/libffi}/src/powerpc/darwin_closure.S +0 -0
  112. data/ext/{libffi → ffi_c/libffi}/src/powerpc/ffi.c +0 -0
  113. data/ext/{libffi → ffi_c/libffi}/src/powerpc/ffi_darwin.c +0 -0
  114. data/ext/{libffi → ffi_c/libffi}/src/powerpc/ffitarget.h +0 -0
  115. data/ext/{libffi → ffi_c/libffi}/src/powerpc/linux64.S +0 -0
  116. data/ext/{libffi → ffi_c/libffi}/src/powerpc/linux64_closure.S +0 -0
  117. data/ext/{libffi → ffi_c/libffi}/src/powerpc/ppc_closure.S +0 -0
  118. data/ext/{libffi → ffi_c/libffi}/src/powerpc/sysv.S +0 -0
  119. data/ext/{libffi → ffi_c/libffi}/src/prep_cif.c +0 -0
  120. data/ext/{libffi → ffi_c/libffi}/src/raw_api.c +0 -0
  121. data/ext/{libffi → ffi_c/libffi}/src/s390/ffi.c +0 -0
  122. data/ext/{libffi → ffi_c/libffi}/src/s390/ffitarget.h +0 -0
  123. data/ext/{libffi → ffi_c/libffi}/src/s390/sysv.S +0 -0
  124. data/ext/{libffi → ffi_c/libffi}/src/sh/ffi.c +0 -0
  125. data/ext/{libffi → ffi_c/libffi}/src/sh/ffitarget.h +0 -0
  126. data/ext/{libffi → ffi_c/libffi}/src/sh/sysv.S +0 -0
  127. data/ext/{libffi → ffi_c/libffi}/src/sh64/ffi.c +0 -0
  128. data/ext/{libffi → ffi_c/libffi}/src/sh64/ffitarget.h +0 -0
  129. data/ext/{libffi → ffi_c/libffi}/src/sh64/sysv.S +0 -0
  130. data/ext/{libffi → ffi_c/libffi}/src/sparc/ffi.c +0 -0
  131. data/ext/{libffi → ffi_c/libffi}/src/sparc/ffitarget.h +0 -0
  132. data/ext/{libffi → ffi_c/libffi}/src/sparc/v8.S +0 -0
  133. data/ext/{libffi → ffi_c/libffi}/src/sparc/v9.S +0 -0
  134. data/ext/{libffi → ffi_c/libffi}/src/types.c +0 -0
  135. data/ext/{libffi → ffi_c/libffi}/src/x86/darwin.S +0 -0
  136. data/ext/{libffi → ffi_c/libffi}/src/x86/darwin64.S +0 -0
  137. data/ext/{libffi → ffi_c/libffi}/src/x86/ffi.c +0 -0
  138. data/ext/{libffi → ffi_c/libffi}/src/x86/ffi64.c +0 -0
  139. data/ext/{libffi → ffi_c/libffi}/src/x86/ffitarget.h +0 -0
  140. data/ext/{libffi → ffi_c/libffi}/src/x86/freebsd.S +0 -0
  141. data/ext/{libffi → ffi_c/libffi}/src/x86/sysv.S +0 -0
  142. data/ext/{libffi → ffi_c/libffi}/src/x86/unix64.S +0 -0
  143. data/ext/{libffi → ffi_c/libffi}/src/x86/win32.S +0 -0
  144. data/ext/{libffi → ffi_c/libffi}/testsuite/Makefile.am +0 -0
  145. data/ext/{libffi → ffi_c/libffi}/testsuite/Makefile.in +0 -0
  146. data/ext/{libffi → ffi_c/libffi}/testsuite/config/default.exp +0 -0
  147. data/ext/{libffi → ffi_c/libffi}/testsuite/lib/libffi-dg.exp +0 -0
  148. data/ext/{libffi → ffi_c/libffi}/testsuite/lib/target-libpath.exp +0 -0
  149. data/ext/{libffi → ffi_c/libffi}/testsuite/lib/wrapper.exp +0 -0
  150. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/call.exp +0 -0
  151. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn0.c +0 -0
  152. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn1.c +0 -0
  153. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn2.c +0 -0
  154. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn3.c +0 -0
  155. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn4.c +0 -0
  156. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn5.c +0 -0
  157. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn6.c +0 -0
  158. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_stdcall.c +0 -0
  159. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_12byte.c +0 -0
  160. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_16byte.c +0 -0
  161. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_18byte.c +0 -0
  162. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_19byte.c +0 -0
  163. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_1_1byte.c +0 -0
  164. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_20byte.c +0 -0
  165. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_20byte1.c +0 -0
  166. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_24byte.c +0 -0
  167. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_2byte.c +0 -0
  168. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_3_1byte.c +0 -0
  169. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_3byte1.c +0 -0
  170. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_3byte2.c +0 -0
  171. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_4_1byte.c +0 -0
  172. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_4byte.c +0 -0
  173. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_5_1_byte.c +0 -0
  174. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_5byte.c +0 -0
  175. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_64byte.c +0 -0
  176. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_6_1_byte.c +0 -0
  177. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_6byte.c +0 -0
  178. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_7_1_byte.c +0 -0
  179. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_7byte.c +0 -0
  180. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_8byte.c +0 -0
  181. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_9byte1.c +0 -0
  182. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_9byte2.c +0 -0
  183. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_double.c +0 -0
  184. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_float.c +0 -0
  185. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_longdouble.c +0 -0
  186. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_pointer.c +0 -0
  187. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_sint16.c +0 -0
  188. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_sint32.c +0 -0
  189. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_sint64.c +0 -0
  190. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_uint16.c +0 -0
  191. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_uint32.c +0 -0
  192. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_uint64.c +0 -0
  193. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_double.c +0 -0
  194. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_float.c +0 -0
  195. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_schar.c +0 -0
  196. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_sshort.c +0 -0
  197. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_sshortchar.c +0 -0
  198. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_uchar.c +0 -0
  199. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_ushort.c +0 -0
  200. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_ushortchar.c +0 -0
  201. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_schar.c +0 -0
  202. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_sint.c +0 -0
  203. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_sshort.c +0 -0
  204. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_uchar.c +0 -0
  205. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_uint.c +0 -0
  206. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_ulonglong.c +0 -0
  207. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_ushort.c +0 -0
  208. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/ffitest.h +0 -0
  209. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float.c +0 -0
  210. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float1.c +0 -0
  211. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float2.c +0 -0
  212. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float3.c +0 -0
  213. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float4.c +0 -0
  214. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/many.c +0 -0
  215. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/many_win32.c +0 -0
  216. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/negint.c +0 -0
  217. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct.c +0 -0
  218. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct1.c +0 -0
  219. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct10.c +0 -0
  220. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct2.c +0 -0
  221. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct3.c +0 -0
  222. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct4.c +0 -0
  223. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct5.c +0 -0
  224. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct6.c +0 -0
  225. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct7.c +0 -0
  226. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct8.c +0 -0
  227. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct9.c +0 -0
  228. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/problem1.c +0 -0
  229. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/promotion.c +0 -0
  230. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/pyobjc-tc.c +0 -0
  231. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_dbl.c +0 -0
  232. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_dbl1.c +0 -0
  233. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_dbl2.c +0 -0
  234. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl.c +0 -0
  235. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl1.c +0 -0
  236. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl2.c +0 -0
  237. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl3.c +0 -0
  238. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ldl.c +0 -0
  239. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ll.c +0 -0
  240. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ll1.c +0 -0
  241. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_sc.c +0 -0
  242. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_sl.c +0 -0
  243. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_uc.c +0 -0
  244. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ul.c +0 -0
  245. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/strlen.c +0 -0
  246. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/strlen_win32.c +0 -0
  247. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct1.c +0 -0
  248. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct2.c +0 -0
  249. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct3.c +0 -0
  250. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct4.c +0 -0
  251. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct5.c +0 -0
  252. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct6.c +0 -0
  253. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct7.c +0 -0
  254. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct8.c +0 -0
  255. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct9.c +0 -0
  256. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/ffitestcxx.h +0 -0
  257. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/special.exp +0 -0
  258. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/unwindtest.cc +0 -0
  259. data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/unwindtest_ffi_call.cc +0 -0
  260. data/ext/{libffi → ffi_c/libffi}/texinfo.tex +0 -0
  261. data/ext/{rbffi.h → ffi_c/rbffi.h} +1 -8
  262. data/lib/ffi/autopointer.rb +7 -7
  263. data/lib/ffi/buffer.rb +0 -25
  264. data/lib/ffi/ffi.rb +1 -0
  265. data/lib/ffi/library.rb +103 -37
  266. data/lib/ffi/memorypointer.rb +25 -28
  267. data/lib/ffi/platform.rb +2 -2
  268. data/lib/ffi/pointer.rb +21 -7
  269. data/lib/ffi/struct.rb +161 -179
  270. data/lib/ffi/types.rb +3 -3
  271. data/lib/ffi/union.rb +17 -0
  272. data/nbproject/configurations.xml +98 -88
  273. data/samples/hello.rb +1 -2
  274. data/samples/sample_helper.rb +6 -0
  275. data/{specs → spec/ffi}/buffer_spec.rb +0 -0
  276. data/{specs → spec/ffi}/callback_spec.rb +114 -89
  277. data/{specs → spec/ffi}/errno_spec.rb +0 -0
  278. data/spec/ffi/library_spec.rb +144 -0
  279. data/{specs → spec/ffi}/managed_struct_spec.rb +12 -1
  280. data/{specs → spec/ffi}/number_spec.rb +34 -16
  281. data/{specs → spec/ffi}/pointer_spec.rb +46 -2
  282. data/{specs → spec/ffi}/rbx/attach_function_spec.rb +2 -1
  283. data/{specs → spec/ffi}/rbx/memory_pointer_spec.rb +19 -19
  284. data/{specs → spec/ffi}/rbx/spec_helper.rb +0 -0
  285. data/{specs → spec/ffi}/rbx/struct_spec.rb +0 -0
  286. data/spec/ffi/spec_helper.rb +13 -0
  287. data/{specs → spec/ffi}/string_spec.rb +8 -0
  288. data/spec/ffi/struct_spec.rb +453 -0
  289. data/{specs → spec/ffi}/typedef_spec.rb +3 -3
  290. data/spec/ffi/union_spec.rb +60 -0
  291. data/{specs → spec/ffi}/variadic_spec.rb +0 -0
  292. data/spec/spec.opts +4 -0
  293. metadata +356 -334
  294. data/README +0 -0
  295. data/ext/Buffer.c +0 -98
  296. data/ext/MemoryPointer.c +0 -99
  297. data/ext/NativeLibrary.c +0 -90
  298. data/ext/Types.c +0 -76
  299. data/ext/ffi.c +0 -64
  300. data/ext/ffi.mk +0 -24
  301. data/ext/libffi.mk +0 -10
  302. data/gen/Rakefile +0 -12
  303. data/specs/library_spec.rb +0 -55
  304. data/specs/spec_helper.rb +0 -9
  305. data/specs/struct_spec.rb +0 -223
@@ -19,17 +19,25 @@ static void autoptr_mark(AutoPointer* ptr);
19
19
  static void autoptr_free(AutoPointer* ptr);
20
20
 
21
21
  static VALUE
22
- autoptr_new(VALUE klass, VALUE other)
22
+ autoptr_allocate(VALUE klass)
23
23
  {
24
24
  AutoPointer* p;
25
- AbstractMemory* ptr;
26
- VALUE retval;
25
+ VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, autoptr_free, p);
26
+ p->parent = Qnil;
27
+ return obj;
28
+ }
29
+
30
+ static VALUE
31
+ autoptr_set_parent(VALUE self, VALUE parent)
32
+ {
33
+ AutoPointer* p;
34
+ AbstractMemory* ptr = rb_FFI_AbstractMemory_cast(parent, rb_FFI_Pointer_class);
27
35
 
28
- retval = Data_Make_Struct(klass, AutoPointer, autoptr_mark, autoptr_free, p);
29
- ptr = (AbstractMemory *) DATA_PTR(other);
36
+ Data_Get_Struct(self, AutoPointer, p);
30
37
  p->memory = *ptr;
31
- p->parent = other;
32
- return retval;
38
+ p->parent = parent;
39
+
40
+ return self;
33
41
  }
34
42
 
35
43
  static void
@@ -50,5 +58,6 @@ rb_FFI_AutoPointer_Init()
50
58
  {
51
59
  VALUE moduleFFI = rb_define_module("FFI");
52
60
  rb_FFI_AutoPointer_class = classAutoPointer = rb_define_class_under(moduleFFI, "AutoPointer", rb_FFI_Pointer_class);
53
- rb_define_singleton_method(classAutoPointer, "__alloc", autoptr_new, 1);
61
+ rb_define_alloc_func(classAutoPointer, autoptr_allocate);
62
+ rb_define_protected_method(classAutoPointer, "parent=", autoptr_set_parent, 1);
54
63
  }
@@ -0,0 +1,136 @@
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 classBuffer = Qnil;
22
+ #define BUFFER(obj) ((Buffer *) rb_FFI_AbstractMemory_cast((obj), classBuffer))
23
+
24
+ static VALUE
25
+ buffer_allocate(VALUE klass)
26
+ {
27
+ Buffer* buffer;
28
+ return Data_Make_Struct(klass, Buffer, buffer_mark, buffer_release, buffer);
29
+ }
30
+
31
+ static VALUE
32
+ buffer_initialize(int argc, VALUE* argv, VALUE self)
33
+ {
34
+ VALUE size = Qnil, count = Qnil, clear = Qnil;
35
+ Buffer* p;
36
+ unsigned long msize;
37
+ void* memory;
38
+ int nargs;
39
+
40
+ nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
41
+ msize = rb_FFI_type_size(size) * (nargs > 1 ? NUM2LONG(count) : 1);
42
+ memory = malloc(msize + 7);
43
+ if (memory == NULL) {
44
+ rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", msize);
45
+ }
46
+ Data_Get_Struct(self, Buffer, p);
47
+ p->storage = memory;
48
+ p->memory.size = msize;
49
+ /* ensure the memory is aligned on at least a 8 byte boundary */
50
+ p->memory.address = (void *) (((uintptr_t) memory + 0x7) & (uintptr_t) ~0x7UL);
51
+ p->parent = Qnil;
52
+ if (nargs > 2 && RTEST(clear) && p->memory.size > 0) {
53
+ memset(p->memory.address, 0, p->memory.size);
54
+ }
55
+ if (rb_block_given_p()) {
56
+ return rb_rescue(rb_yield, self, buffer_free, self);
57
+ }
58
+ return self;
59
+ }
60
+
61
+ static VALUE
62
+ buffer_alloc_inout(int argc, VALUE* argv, VALUE klass)
63
+ {
64
+ return buffer_initialize(argc, argv, buffer_allocate(klass));
65
+ }
66
+
67
+ static VALUE
68
+ buffer_plus(VALUE self, VALUE offset)
69
+ {
70
+ Buffer* ptr = BUFFER(self);
71
+ Buffer* p;
72
+ VALUE retval;
73
+ long off = NUM2LONG(offset);
74
+
75
+ checkBounds(&ptr->memory, off, 1);
76
+ retval = Data_Make_Struct(classBuffer, Buffer, buffer_mark, buffer_release, p);
77
+ p->memory.address = ptr->memory.address + off;;
78
+ p->memory.size = ptr->memory.size - off;
79
+ p->parent = self;
80
+ return retval;
81
+ }
82
+
83
+ static VALUE
84
+ buffer_inspect(VALUE self)
85
+ {
86
+ char tmp[100];
87
+ snprintf(tmp, sizeof(tmp), "#<Buffer size=%ld>", BUFFER(self)->memory.size);
88
+ return rb_str_new2(tmp);
89
+ }
90
+
91
+ /* Only used to free the buffer if the yield in the initializer throws an exception */
92
+ static VALUE
93
+ buffer_free(VALUE self)
94
+ {
95
+ Buffer* ptr = BUFFER(self);
96
+ if (ptr->parent == Qnil && ptr->storage != NULL) {
97
+ free(ptr->storage);
98
+ ptr->storage = NULL;
99
+ }
100
+ return self;
101
+ }
102
+
103
+ static void
104
+ buffer_release(Buffer* ptr)
105
+ {
106
+ if (ptr->parent == Qnil && ptr->storage != NULL) {
107
+ free(ptr->storage);
108
+ ptr->storage = NULL;
109
+ }
110
+ xfree(ptr);
111
+ }
112
+
113
+ static void
114
+ buffer_mark(Buffer* ptr)
115
+ {
116
+ if (ptr->parent != Qnil) {
117
+ rb_gc_mark(ptr->parent);
118
+ }
119
+ }
120
+
121
+ void
122
+ rb_FFI_Buffer_Init()
123
+ {
124
+ VALUE moduleFFI = rb_define_module("FFI");
125
+ classBuffer = rb_define_class_under(moduleFFI, "Buffer", rb_FFI_AbstractMemory_class);
126
+ rb_define_alloc_func(classBuffer, buffer_allocate);
127
+
128
+ rb_define_singleton_method(classBuffer, "alloc_inout", buffer_alloc_inout, -1);
129
+ rb_define_singleton_method(classBuffer, "alloc_out", buffer_alloc_inout, -1);
130
+ rb_define_singleton_method(classBuffer, "alloc_in", buffer_alloc_inout, -1);
131
+
132
+ rb_define_method(classBuffer, "initialize", buffer_initialize, -1);
133
+ rb_define_method(classBuffer, "inspect", buffer_inspect, 0);
134
+ rb_define_method(classBuffer, "+", buffer_plus, 1);
135
+ }
136
+
@@ -1,6 +1,8 @@
1
1
  #include <sys/param.h>
2
2
  #include <sys/types.h>
3
- #include <sys/mman.h>
3
+ #ifndef _WIN32
4
+ # include <sys/mman.h>
5
+ #endif
4
6
  #include <ruby.h>
5
7
  #include <ffi.h>
6
8
  #include "AbstractMemory.h"
@@ -26,7 +28,7 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
26
28
 
27
29
  static VALUE classCallbackInfo = Qnil;
28
30
  static VALUE classNativeCallback = Qnil;
29
- static ID callID = Qnil;
31
+ static ID callID = Qnil, cbTableID = Qnil;
30
32
 
31
33
  VALUE rb_FFI_CallbackInfo_class = Qnil;
32
34
 
@@ -55,7 +57,7 @@ CallbackInfo_new(VALUE klass, VALUE rbReturnType, VALUE rbParamTypes)
55
57
  if (cbInfo->ffiReturnType == NULL) {
56
58
  rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType);
57
59
  }
58
- #ifdef _WIN32
60
+ #if defined(_WIN32) && defined(notyet)
59
61
  cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
60
62
  #else
61
63
  cbInfo->abi = FFI_DEFAULT_ABI;
@@ -126,41 +128,41 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
126
128
  for (i = 0; i < cbInfo->parameterCount; ++i) {
127
129
  VALUE param;
128
130
  switch (cbInfo->parameterTypes[i]) {
129
- case INT8:
131
+ case NATIVE_INT8:
130
132
  param = INT2NUM(*(int8_t *) parameters[i]);
131
133
  break;
132
- case UINT8:
133
- param = UINT2NUM(*(u_int8_t *) parameters[i]);
134
+ case NATIVE_UINT8:
135
+ param = UINT2NUM(*(uint8_t *) parameters[i]);
134
136
  break;
135
- case INT16:
137
+ case NATIVE_INT16:
136
138
  param = INT2NUM(*(int16_t *) parameters[i]);
137
139
  break;
138
- case UINT16:
139
- param = UINT2NUM(*(u_int16_t *) parameters[i]);
140
+ case NATIVE_UINT16:
141
+ param = UINT2NUM(*(uint16_t *) parameters[i]);
140
142
  break;
141
- case INT32:
143
+ case NATIVE_INT32:
142
144
  param = INT2NUM(*(int32_t *) parameters[i]);
143
145
  break;
144
- case UINT32:
145
- param = UINT2NUM(*(u_int32_t *) parameters[i]);
146
+ case NATIVE_UINT32:
147
+ param = UINT2NUM(*(uint32_t *) parameters[i]);
146
148
  break;
147
- case INT64:
149
+ case NATIVE_INT64:
148
150
  param = LL2NUM(*(int64_t *) parameters[i]);
149
151
  break;
150
- case UINT64:
151
- param = ULL2NUM(*(u_int64_t *) parameters[i]);
152
+ case NATIVE_UINT64:
153
+ param = ULL2NUM(*(uint64_t *) parameters[i]);
152
154
  break;
153
- case FLOAT32:
155
+ case NATIVE_FLOAT32:
154
156
  param = rb_float_new(*(float *) parameters[i]);
155
157
  break;
156
- case FLOAT64:
158
+ case NATIVE_FLOAT64:
157
159
  param = rb_float_new(*(double *) parameters[i]);
158
160
  break;
159
- case STRING:
161
+ case NATIVE_STRING:
160
162
  param = rb_tainted_str_new2(*(char **) parameters[i]);
161
163
  break;
162
- case POINTER:
163
- param = rb_FFI_Pointer_new(*(caddr_t *) parameters[i]);
164
+ case NATIVE_POINTER:
165
+ param = rb_FFI_Pointer_new(*(void **) parameters[i]);
164
166
  break;
165
167
  default:
166
168
  param = Qnil;
@@ -172,30 +174,35 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
172
174
  if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
173
175
  memset(retval, 0, cbInfo->ffiReturnType->size);
174
176
  } else switch (cbInfo->returnType) {
175
- case INT8:
176
- case INT16:
177
- case INT32:
178
- *((long *) retval) = NUM2INT(rbReturnValue);
177
+ case NATIVE_INT8:
178
+ case NATIVE_INT16:
179
+ case NATIVE_INT32:
180
+ *((ffi_sarg *) retval) = NUM2INT(rbReturnValue);
179
181
  break;
180
- case UINT8:
181
- case UINT16:
182
- case UINT32:
183
- *((unsigned long *) retval) = NUM2UINT(rbReturnValue);
182
+ case NATIVE_UINT8:
183
+ case NATIVE_UINT16:
184
+ case NATIVE_UINT32:
185
+ *((ffi_arg *) retval) = NUM2UINT(rbReturnValue);
184
186
  break;
185
- case INT64:
187
+ case NATIVE_INT64:
186
188
  *((int64_t *) retval) = NUM2LL(rbReturnValue);
187
189
  break;
188
- case UINT64:
189
- *((u_int64_t *) retval) = NUM2ULL(rbReturnValue);
190
+ case NATIVE_UINT64:
191
+ *((uint64_t *) retval) = NUM2ULL(rbReturnValue);
190
192
  break;
191
- case FLOAT32:
193
+ case NATIVE_FLOAT32:
192
194
  *((float *) retval) = (float) NUM2DBL(rbReturnValue);
193
195
  break;
194
- case FLOAT64:
196
+ case NATIVE_FLOAT64:
195
197
  *((double *) retval) = NUM2DBL(rbReturnValue);
196
198
  break;
197
- case POINTER:
198
- *((caddr_t *) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
199
+ case NATIVE_POINTER:
200
+ if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rb_FFI_Pointer_class)) {
201
+ *((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
202
+ } else {
203
+ // Default to returning NULL if not a value pointer object. handles nil case as well
204
+ *((void **) retval) = NULL;
205
+ }
199
206
  break;
200
207
  default:
201
208
  break;
@@ -228,6 +235,23 @@ rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
228
235
  return Data_Wrap_Struct(classNativeCallback, native_callback_mark, native_callback_free, closure);
229
236
  }
230
237
 
238
+ VALUE
239
+ rb_FFI_NativeCallback_for_proc(VALUE proc, VALUE cbInfo)
240
+ {
241
+ VALUE callback;
242
+ VALUE cbTable = RTEST(rb_ivar_defined(proc, cbTableID)) ? rb_ivar_get(proc, cbTableID) : Qnil;
243
+ if (cbTable == Qnil) {
244
+ cbTable = rb_hash_new();
245
+ rb_ivar_set(proc, cbTableID, cbTable);
246
+ }
247
+ callback = rb_hash_aref(cbTable, cbInfo);
248
+ if (callback != Qnil) {
249
+ return callback;
250
+ }
251
+ callback = rb_FFI_NativeCallback_new(cbInfo, proc);
252
+ rb_hash_aset(cbTable, cbInfo, callback);
253
+ return callback;
254
+ }
231
255
  #if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
232
256
  /*
233
257
  * versions of ffi_closure_alloc, ffi_closure_free and ffi_prep_closure_loc for older
@@ -275,4 +299,5 @@ rb_FFI_Callback_Init()
275
299
  rb_define_singleton_method(classCallbackInfo, "new", CallbackInfo_new, 2);
276
300
  classNativeCallback = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
277
301
  callID = rb_intern("call");
302
+ cbTableID = rb_intern("@__ffi_callback_table__");
278
303
  }
@@ -1,10 +1,3 @@
1
- /*
2
- * File: Callback.h
3
- * Author: wayne
4
- *
5
- * Created on September 11, 2008, 10:01 AM
6
- */
7
-
8
1
  #ifndef _CALLBACK_H
9
2
  #define _CALLBACK_H
10
3
 
@@ -38,6 +31,7 @@ typedef struct {
38
31
 
39
32
  extern VALUE rb_FFI_CallbackInfo_class;
40
33
  extern VALUE rb_FFI_NativeCallback_new(VALUE, VALUE);
34
+ extern VALUE rb_FFI_NativeCallback_for_proc(VALUE proc, VALUE cbInfo);
41
35
 
42
36
  #ifdef __cplusplus
43
37
  }
@@ -1,12 +1,17 @@
1
+ #include <sys/param.h>
1
2
  #include <sys/types.h>
3
+ #ifndef _WIN32
4
+ # include <sys/mman.h>
5
+ #endif
2
6
  #include <stdio.h>
3
7
  #include <stdint.h>
4
- #include <dlfcn.h>
8
+ #include <stdbool.h>
9
+ #include <unistd.h>
5
10
  #include <errno.h>
6
11
  #include <ruby.h>
7
12
 
8
13
  #include <ffi.h>
9
- #ifdef HAVE_NATIVETHREAD
14
+ #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
10
15
  # include <pthread.h>
11
16
  #endif
12
17
  #include "rbffi.h"
@@ -14,11 +19,23 @@
14
19
 
15
20
  #include "AbstractMemory.h"
16
21
  #include "Pointer.h"
22
+ #include "Struct.h"
17
23
  #include "Platform.h"
18
24
  #include "Callback.h"
19
25
  #include "Types.h"
20
26
 
21
- typedef struct Invoker {
27
+ #if defined(__i386__) && !defined(_WIN32) && !defined(__WIN32__)
28
+ # define USE_RAW
29
+ #endif
30
+ #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
31
+ # define USE_PTHREAD_LOCAL
32
+ #endif
33
+ #define MAX_FIXED_ARITY (3)
34
+
35
+ typedef struct MethodHandle MethodHandle;
36
+ typedef struct Invoker Invoker;
37
+
38
+ struct Invoker {
22
39
  VALUE library;
23
40
  void* function;
24
41
  ffi_cif cif;
@@ -30,11 +47,36 @@ typedef struct Invoker {
30
47
  int callbackCount;
31
48
  VALUE* callbackParameters;
32
49
  ffi_abi abi;
33
- } Invoker;
50
+ MethodHandle* methodHandle;
51
+ };
52
+ #ifdef USE_RAW
53
+ # define METHOD_CLOSURE ffi_raw_closure
54
+ #else
55
+ # define METHOD_CLOSURE ffi_closure
56
+ #endif
57
+ typedef struct MethodHandlePool MethodHandlePool;
58
+ struct MethodHandle {
59
+ Invoker* invoker;
60
+ int arity;
61
+ METHOD_CLOSURE* closure;
62
+ void* code;
63
+ ffi_cif cif;
64
+ struct MethodHandlePool* pool;
65
+ MethodHandle* next;
66
+ };
67
+ #if !defined(_WIN32) && !defined(__WIN32__)
68
+ struct MethodHandlePool {
69
+ #ifdef HAVE_NATIVETHREAD
70
+ pthread_mutex_t mutex;
71
+ #endif
72
+ MethodHandle* list;
73
+ };
74
+ #endif /* _WIN32 */
34
75
  typedef struct ThreadData {
35
76
  int td_errno;
36
77
  } ThreadData;
37
- static VALUE invoker_new(VALUE self, VALUE library, VALUE function, VALUE parameterTypes,
78
+ static VALUE invoker_allocate(VALUE klass);
79
+ static VALUE invoker_initialize(VALUE self, VALUE library, VALUE function, VALUE parameterTypes,
38
80
  VALUE returnType, VALUE convention);
39
81
  static void invoker_mark(Invoker *);
40
82
  static void invoker_free(Invoker *);
@@ -42,20 +84,32 @@ static VALUE invoker_call(int argc, VALUE* argv, VALUE self);
42
84
  static VALUE invoker_call0(VALUE self);
43
85
  static VALUE invoker_arity(VALUE self);
44
86
  static void* callback_param(VALUE proc, VALUE cbinfo);
87
+ #ifdef USE_RAW
88
+ static void attached_method_invoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data);
89
+ static void attached_method_vinvoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data);
90
+ #else
91
+ #ifndef _WIN32
92
+ static void attached_method_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
93
+ #endif /* _WIN32 */
94
+ static void attached_method_vinvoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
95
+ #endif
96
+ static MethodHandle* method_handle_alloc(int arity);
97
+ static void method_handle_free(MethodHandle *);
98
+
45
99
  static inline ThreadData* thread_data_get(void);
100
+
101
+ #ifndef _WIN32
102
+ static int PageSize;
103
+ #endif
46
104
  static VALUE classInvoker = Qnil, classVariadicInvoker = Qnil;
47
- static ID cbTableID, to_ptr;
105
+ static ID to_ptr;
48
106
 
49
- #ifdef HAVE_NATIVETHREAD
107
+ #if defined(USE_PTHREAD_LOCAL)
50
108
  static pthread_key_t threadDataKey;
51
109
  #endif
52
110
 
53
111
  #define threadData (thread_data_get())
54
112
 
55
- #if defined(__i386__)
56
- # define USE_RAW
57
- #endif
58
-
59
113
  #ifdef USE_RAW
60
114
  # ifndef __i386__
61
115
  # error "RAW argument packing only supported on i386"
@@ -79,21 +133,26 @@ static pthread_key_t threadDataKey;
79
133
  #endif /* USE_RAW */
80
134
 
81
135
  #ifdef USE_RAW
82
- # define ADJ(p, a) ((p) = (FFIStorage*) (((caddr_t) p) + a##_ADJ))
136
+ # define ADJ(p, a) ((p) = (FFIStorage*) (((char *) p) + a##_ADJ))
83
137
  #else
84
138
  # define ADJ(p, a) (++(p))
85
139
  #endif
86
140
 
141
+ static VALUE
142
+ invoker_allocate(VALUE klass)
143
+ {
144
+ Invoker *invoker;
145
+ return Data_Make_Struct(klass, Invoker, invoker_mark, invoker_free, invoker);
146
+ }
87
147
 
88
148
  static VALUE
89
- invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
149
+ invoker_initialize(VALUE self, VALUE library, VALUE function, VALUE parameterTypes,
90
150
  VALUE returnType, VALUE convention)
91
151
  {
92
152
  Invoker* invoker = NULL;
93
153
  ffi_type* ffiReturnType;
94
154
  ffi_abi abi;
95
155
  ffi_status ffiStatus;
96
- VALUE retval = Qnil;
97
156
  int i;
98
157
 
99
158
  Check_Type(parameterTypes, T_ARRAY);
@@ -101,10 +160,10 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
101
160
  Check_Type(convention, T_STRING);
102
161
  Check_Type(library, T_DATA);
103
162
  Check_Type(function, T_DATA);
104
-
105
- retval = Data_Make_Struct(klass, Invoker, invoker_mark, invoker_free, invoker);
163
+
164
+ Data_Get_Struct(self, Invoker, invoker);
106
165
  invoker->library = library;
107
- invoker->function = ((AbstractMemory *) DATA_PTR(function))->address;
166
+ invoker->function = rb_FFI_AbstractMemory_cast(function, rb_FFI_Pointer_class)->address;
108
167
  invoker->paramCount = RARRAY_LEN(parameterTypes);
109
168
  invoker->paramTypes = ALLOC_N(NativeType, invoker->paramCount);
110
169
  invoker->ffiParamTypes = ALLOC_N(ffi_type *, invoker->paramCount);
@@ -115,7 +174,7 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
115
174
  invoker->callbackParameters = REALLOC_N(invoker->callbackParameters, VALUE,
116
175
  invoker->callbackCount + 1);
117
176
  invoker->callbackParameters[invoker->callbackCount++] = entry;
118
- invoker->paramTypes[i] = CALLBACK;
177
+ invoker->paramTypes[i] = NATIVE_CALLBACK;
119
178
  invoker->ffiParamTypes[i] = &ffi_type_pointer;
120
179
  } else {
121
180
  int paramType = FIX2INT(entry);
@@ -131,8 +190,8 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
131
190
  if (ffiReturnType == NULL) {
132
191
  rb_raise(rb_eArgError, "Invalid return type");
133
192
  }
134
- #ifdef _WIN32
135
- abi = strcmp(StringValueCPtr(convention), "stdcall") == 0 ? FFI_STDCALL : FFI_DEFAULT_ABI;
193
+ #if defined(_WIN32) || defined(__WIN32__)
194
+ abi = strcmp(StringValueCStr(convention), "stdcall") == 0 ? FFI_STDCALL : FFI_DEFAULT_ABI;
136
195
  #else
137
196
  abi = FFI_DEFAULT_ABI;
138
197
  #endif
@@ -148,8 +207,9 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
148
207
  default:
149
208
  rb_raise(rb_eArgError, "Unknown FFI error");
150
209
  }
151
-
152
- return retval;
210
+ invoker->methodHandle = method_handle_alloc(invoker->callbackCount < 1 ? invoker->paramCount : -1);
211
+ invoker->methodHandle->invoker = invoker;
212
+ return self;
153
213
  }
154
214
 
155
215
  static VALUE
@@ -165,9 +225,9 @@ variadic_invoker_new(VALUE klass, VALUE library, VALUE function, VALUE returnTyp
165
225
 
166
226
  retval = Data_Make_Struct(klass, Invoker, invoker_mark, invoker_free, invoker);
167
227
  invoker->library = library;
168
- invoker->function = ((AbstractMemory *) DATA_PTR(function))->address;
169
- #ifdef _WIN32
170
- invoker->abi = strcmp(StringValueCPtr(convention), "stdcall") == 0 ? FFI_STDCALL : FFI_DEFAULT_ABI;
228
+ invoker->function = rb_FFI_AbstractMemory_cast(function, rb_FFI_Pointer_class)->address;
229
+ #if defined(_WIN32) || defined(__WIN32__)
230
+ invoker->abi = strcmp(StringValueCStr(convention), "stdcall") == 0 ? FFI_STDCALL : FFI_DEFAULT_ABI;
171
231
  #else
172
232
  invoker->abi = FFI_DEFAULT_ABI;
173
233
  #endif
@@ -176,9 +236,201 @@ variadic_invoker_new(VALUE klass, VALUE library, VALUE function, VALUE returnTyp
176
236
  return retval;
177
237
  }
178
238
 
239
+ static ffi_type* methodHandleParamTypes[MAX_FIXED_ARITY + 2];
240
+ static ffi_type* methodHandleVarargParamTypes[]= {
241
+ &ffi_type_sint,
242
+ &ffi_type_pointer,
243
+ NULL,
244
+ };
245
+
246
+ #if defined(_WIN32) || defined(__WIN32__)
247
+ static MethodHandle*
248
+ method_handle_alloc(int arity)
249
+ {
250
+ char errmsg[1024];
251
+ ffi_type* ffiReturnType = (sizeof (VALUE) == sizeof (long))
252
+ ? &ffi_type_ulong : &ffi_type_uint64;
253
+ int ffiParamCount, ffiStatus;
254
+ MethodHandle* method = NULL;
255
+ ffi_type** ffiParamTypes;
256
+ void (*fn)(ffi_cif* cif, void* retval, void** parameters, void* user_data);
257
+
258
+ ffiParamCount = 3;
259
+ ffiParamTypes = methodHandleVarargParamTypes;
260
+ fn = attached_method_vinvoke;
261
+ method = ALLOC_N(MethodHandle, 1);
262
+ memset(method, 0, sizeof(*method));
263
+ method->arity = -1;
264
+ ffiStatus = ffi_prep_cif(&method->cif, FFI_DEFAULT_ABI, ffiParamCount,
265
+ ffiReturnType, ffiParamTypes);
266
+ if (ffiStatus != FFI_OK) {
267
+ snprintf(errmsg, sizeof (errmsg), "ffi_prep_cif failed. status=%#x", ffiStatus);
268
+ goto error;
269
+ }
270
+ method->closure = ffi_closure_alloc(sizeof(*method->closure), &method->code);
271
+ if (method->closure == NULL) {
272
+ snprintf(errmsg, sizeof(errmsg), "ffi_closure_alloc failed");
273
+ goto error;
274
+ }
275
+ ffiStatus = ffi_prep_closure_loc(method->closure, &method->cif, fn, method, method->code);
276
+ if (ffiStatus != FFI_OK) {
277
+ snprintf(errmsg, sizeof (errmsg), "ffi_prep_closure failed. status=%#x", ffiStatus);
278
+ goto error;
279
+ }
280
+ return method;
281
+ error:
282
+ if (method != NULL) {
283
+ if (method->closure != NULL) {
284
+ ffi_closure_free(method->closure);
285
+ }
286
+ xfree(method);
287
+ }
288
+ rb_raise(rb_eRuntimeError, "%s", errmsg);
289
+ }
290
+ static void
291
+ method_handle_free(MethodHandle* method)
292
+ {
293
+ if (method->closure != NULL) {
294
+ ffi_closure_free(method->closure);
295
+ }
296
+ xfree(method);
297
+ }
298
+ #else
299
+ static MethodHandlePool methodHandlePool[MAX_FIXED_ARITY + 1], defaultMethodHandlePool;
300
+
301
+ #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32)
302
+ # define pool_lock(p) pthread_mutex_lock(&(p)->mutex)
303
+ # define pool_unlock(p) pthread_mutex_unlock(&(p)->mutex)
304
+ #else
305
+ # define pool_lock(p)
306
+ # define pool_unlock(p)
307
+ #endif
308
+ static MethodHandle*
309
+ method_handle_alloc(int arity)
310
+ {
311
+ MethodHandle* method, *list = NULL;
312
+ MethodHandlePool* pool;
313
+ ffi_type** ffiParamTypes;
314
+ ffi_type* ffiReturnType;
315
+ caddr_t page;
316
+ int ffiParamCount, ffiStatus;
317
+ int nclosures, closureSize, methodArity;
318
+ int i;
319
+ #ifdef USE_RAW
320
+ void (*fn)(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data);
321
+ #else
322
+ void (*fn)(ffi_cif* cif, void* retval, void** parameters, void* user_data);
323
+ #endif
324
+
325
+
326
+ pool = (arity >= 0 && arity <= MAX_FIXED_ARITY) ? &methodHandlePool[arity] : &defaultMethodHandlePool;
327
+ pool_lock(pool);
328
+ if (pool->list != NULL) {
329
+ method = pool->list;
330
+ pool->list = pool->list->next;
331
+ pool_unlock(pool);
332
+ return method;
333
+ }
334
+ ffiReturnType = (sizeof (VALUE) == sizeof (long))
335
+ ? &ffi_type_ulong : &ffi_type_uint64;
336
+ closureSize = roundup(sizeof(METHOD_CLOSURE), 8);
337
+ nclosures = PageSize / closureSize;
338
+ page = mmap(NULL, PageSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
339
+ if (page == (caddr_t) -1) {
340
+ pool_unlock(pool);
341
+ rb_raise(rb_eRuntimeError, "mmap failed. errno=%d (%s)", errno, strerror(errno));
342
+ }
343
+
344
+ /* figure out whichh function to bounce the execution through */
345
+ if (arity >= 0 && arity <= MAX_FIXED_ARITY) {
346
+ ffiParamCount = arity + 1;
347
+ ffiParamTypes = methodHandleParamTypes;
348
+ fn = attached_method_invoke;
349
+ methodArity = arity;
350
+ } else {
351
+ ffiParamCount = 3;
352
+ ffiParamTypes = methodHandleVarargParamTypes;
353
+ fn = attached_method_vinvoke;
354
+ methodArity = -1;
355
+ }
356
+
357
+ for (i = 0; i < nclosures; ++i) {
358
+ char errmsg[256];
359
+ method = calloc(1, sizeof(MethodHandle));
360
+ if (method == NULL) {
361
+ snprintf(errmsg, sizeof(errmsg), "malloc failed: %s", strerror(errno));
362
+ goto error;
363
+ }
364
+ method->next = list;
365
+ list = method;
366
+ method->pool = pool;
367
+ method->code = method->closure = (METHOD_CLOSURE *) (page + (i * closureSize));
368
+
369
+ ffiStatus = ffi_prep_cif(&method->cif, FFI_DEFAULT_ABI, ffiParamCount,
370
+ ffiReturnType, ffiParamTypes);
371
+ if (ffiStatus != FFI_OK) {
372
+ snprintf(errmsg, sizeof(errmsg), "ffi_prep_cif failed. status=%#x", ffiStatus);
373
+ goto error;
374
+ }
375
+
376
+ #ifdef USE_RAW
377
+ ffiStatus = ffi_prep_raw_closure(method->closure, &method->cif, fn, method);
378
+ #else
379
+ ffiStatus = ffi_prep_closure(method->closure, &method->cif, fn, method);
380
+ #endif
381
+ if (ffiStatus != FFI_OK) {
382
+ snprintf(errmsg, sizeof(errmsg), "ffi_prep_closure failed. status=%#x", ffiStatus);
383
+ goto error;
384
+ }
385
+ method->arity = methodArity;
386
+ continue;
387
+ error:
388
+ while (list != NULL) {
389
+ method = list;
390
+ list = list->next;
391
+ free(method);
392
+ }
393
+ munmap(page, PageSize);
394
+ pool_unlock(pool);
395
+ rb_raise(rb_eRuntimeError, "%s", errmsg);
396
+ }
397
+ mprotect(page, PageSize, PROT_READ | PROT_EXEC);
398
+
399
+ /* take the first member of the list for this handle */
400
+ method = list;
401
+ list = list->next;
402
+
403
+ /* now add the new block of MethodHandles to the pool */
404
+ if (list != NULL) {
405
+ list->next = pool->list;
406
+ pool->list = list;
407
+ }
408
+ pool_unlock(pool);
409
+ return method;
410
+ }
411
+ static void
412
+ method_handle_free(MethodHandle* method)
413
+ {
414
+ MethodHandlePool* pool = method->pool;
415
+ pool_lock(pool);
416
+ method->next = pool->list;
417
+ pool->list = method;
418
+ pool_unlock(pool);
419
+ }
420
+ #endif /* _WIN32 */
421
+
179
422
  typedef union {
180
- signed long i;
181
- unsigned long u;
423
+ #if BYTE_ORDER == LITTLE_ENDIAN
424
+ signed int s8, s16, s32;
425
+ unsigned int u8, u16, u32;
426
+ #else
427
+ signed char s8;
428
+ unsigned char u8;
429
+ signed short s16;
430
+ unsigned short u16;
431
+ signed int s32;
432
+ unsigned int u32;
433
+ #endif
182
434
  signed long long i64;
183
435
  unsigned long long u64;
184
436
  void* ptr;
@@ -250,32 +502,32 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
250
502
  ffiValues[i] = param;
251
503
 
252
504
  switch (paramTypes[i]) {
253
- case INT8:
254
- param->i = getSignedInt(argv[argidx++], type, -128, 127, "char");
505
+ case NATIVE_INT8:
506
+ param->s8 = getSignedInt(argv[argidx++], type, -128, 127, "char");
255
507
  ADJ(param, INT8);
256
508
  break;
257
- case INT16:
258
- param->i = getSignedInt(argv[argidx++], type, -0x8000, 0x7fff, "short");
509
+ case NATIVE_INT16:
510
+ param->s16 = getSignedInt(argv[argidx++], type, -0x8000, 0x7fff, "short");
259
511
  ADJ(param, INT16);
260
512
  break;
261
- case INT32:
262
- param->i = getSignedInt(argv[argidx++], type, -0x80000000, 0x7fffffff, "int");
513
+ case NATIVE_INT32:
514
+ param->s32 = getSignedInt(argv[argidx++], type, -0x80000000, 0x7fffffff, "int");
263
515
  ADJ(param, INT32);
264
516
  break;
265
- case UINT8:
266
- param->u = getUnsignedInt(argv[argidx++], type, 0xff, "unsigned char");
517
+ case NATIVE_UINT8:
518
+ param->u8 = getUnsignedInt(argv[argidx++], type, 0xff, "unsigned char");
267
519
  ADJ(param, INT8);
268
520
  break;
269
- case UINT16:
270
- param->u = getUnsignedInt(argv[argidx++], type, 0xffff, "unsigned short");
521
+ case NATIVE_UINT16:
522
+ param->u16 = getUnsignedInt(argv[argidx++], type, 0xffff, "unsigned short");
271
523
  ADJ(param, INT16);
272
524
  break;
273
- case UINT32:
525
+ case NATIVE_UINT32:
274
526
  /* Special handling/checking for unsigned 32 bit integers */
275
- param->u = getUnsignedInt32(argv[argidx++], type);
527
+ param->u32 = getUnsignedInt32(argv[argidx++], type);
276
528
  ADJ(param, INT32);
277
529
  break;
278
- case INT64:
530
+ case NATIVE_INT64:
279
531
  if (type != T_FIXNUM && type != T_BIGNUM) {
280
532
  rb_raise(rb_eTypeError, "Expected an Integer parameter");
281
533
  }
@@ -283,15 +535,15 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
283
535
  ADJ(param, INT64);
284
536
  ++argidx;
285
537
  break;
286
- case UINT64:
538
+ case NATIVE_UINT64:
287
539
  if (type != T_FIXNUM && type != T_BIGNUM) {
288
540
  rb_raise(rb_eTypeError, "Expected an Integer parameter");
289
541
  }
290
- param->i64 = NUM2ULL(argv[argidx]);
542
+ param->u64 = NUM2ULL(argv[argidx]);
291
543
  ADJ(param, INT64);
292
544
  ++argidx;
293
545
  break;
294
- case FLOAT32:
546
+ case NATIVE_FLOAT32:
295
547
  if (type != T_FLOAT && type != T_FIXNUM) {
296
548
  rb_raise(rb_eTypeError, "Expected a Float parameter");
297
549
  }
@@ -299,7 +551,7 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
299
551
  ADJ(param, FLOAT32);
300
552
  ++argidx;
301
553
  break;
302
- case FLOAT64:
554
+ case NATIVE_FLOAT64:
303
555
  if (type != T_FLOAT && type != T_FIXNUM) {
304
556
  rb_raise(rb_eTypeError, "Expected a Float parameter");
305
557
  }
@@ -307,12 +559,12 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
307
559
  ADJ(param, FLOAT64);
308
560
  ++argidx;
309
561
  break;
310
- case STRING:
562
+ case NATIVE_STRING:
311
563
  if (type == T_STRING) {
312
564
  if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) {
313
565
  rb_raise(rb_eSecurityError, "Unsafe string parameter");
314
566
  }
315
- param->ptr = StringValuePtr(argv[argidx]);
567
+ param->ptr = StringValueCStr(argv[argidx]);
316
568
  } else if (type == T_NIL) {
317
569
  param->ptr = NULL;
318
570
  } else {
@@ -321,12 +573,15 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
321
573
  ADJ(param, ADDRESS);
322
574
  ++argidx;
323
575
  break;
324
- case POINTER:
325
- case BUFFER_IN:
326
- case BUFFER_OUT:
327
- case BUFFER_INOUT:
328
- if (rb_obj_is_kind_of(argv[argidx], rb_FFI_AbstractMemory_class) && type == T_DATA) {
576
+ case NATIVE_POINTER:
577
+ case NATIVE_BUFFER_IN:
578
+ case NATIVE_BUFFER_OUT:
579
+ case NATIVE_BUFFER_INOUT:
580
+ if (type == T_DATA && rb_obj_is_kind_of(argv[argidx], rb_FFI_AbstractMemory_class)) {
329
581
  param->ptr = ((AbstractMemory *) DATA_PTR(argv[argidx]))->address;
582
+ } else if (type == T_DATA && rb_obj_is_kind_of(argv[argidx], rb_FFI_Struct_class)) {
583
+ AbstractMemory* memory = ((Struct *) DATA_PTR(argv[argidx]))->pointer;
584
+ param->ptr = memory != NULL ? memory->address : NULL;
330
585
  } else if (type == T_STRING) {
331
586
  if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) {
332
587
  rb_raise(rb_eSecurityError, "Unsafe string parameter");
@@ -336,7 +591,7 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
336
591
  param->ptr = NULL;
337
592
  } else if (rb_respond_to(argv[argidx], to_ptr)) {
338
593
  VALUE ptr = rb_funcall2(argv[argidx], to_ptr, 0, NULL);
339
- if (rb_obj_is_kind_of(ptr, rb_FFI_Pointer_class) && TYPE(ptr) == T_DATA) {
594
+ if (rb_obj_is_kind_of(ptr, rb_FFI_AbstractMemory_class) && TYPE(ptr) == T_DATA) {
340
595
  param->ptr = ((AbstractMemory *) DATA_PTR(ptr))->address;
341
596
  } else {
342
597
  rb_raise(rb_eArgError, "to_ptr returned an invalid pointer");
@@ -348,7 +603,7 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
348
603
  ADJ(param, ADDRESS);
349
604
  ++argidx;
350
605
  break;
351
- case CALLBACK:
606
+ case NATIVE_CALLBACK:
352
607
  if (callbackProc != Qnil) {
353
608
  param->ptr = callback_param(callbackProc, invoker->callbackParameters[cbidx++]);
354
609
  } else {
@@ -371,7 +626,11 @@ ffi_invoke(ffi_cif* cif, void* function, NativeType returnType, void** ffiValues
371
626
  #else
372
627
  ffi_call(cif, FFI_FN(function), &retval, ffiValues);
373
628
  #endif
629
+ #if defined(_WIN32) || defined(__WIN32__)
630
+ threadData->td_errno = GetLastError();
631
+ #else
374
632
  threadData->td_errno = errno;
633
+ #endif
375
634
  return rb_FFI_NativeValueToRuby(returnType, &retval);
376
635
  }
377
636
  static VALUE
@@ -386,6 +645,18 @@ invoker_call(int argc, VALUE* argv, VALUE self)
386
645
  return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
387
646
  }
388
647
 
648
+ static inline VALUE
649
+ invoker_callN(VALUE self, int argc, VALUE* argv)
650
+ {
651
+ Invoker* invoker;
652
+ FFIStorage params[3];
653
+ void* ffiValues[3];
654
+
655
+ Data_Get_Struct(self, Invoker, invoker);
656
+ ffi_arg_setup(invoker, argc, argv, invoker->paramTypes, params, ffiValues);
657
+ return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
658
+ }
659
+
389
660
  static VALUE
390
661
  invoker_call0(VALUE self)
391
662
  {
@@ -400,41 +671,102 @@ invoker_call0(VALUE self)
400
671
  static VALUE
401
672
  invoker_call1(VALUE self, VALUE arg1)
402
673
  {
403
- Invoker* invoker;
404
- void* ffiValues[1];
405
- FFIStorage params[1];
406
-
407
- Data_Get_Struct(self, Invoker, invoker);
408
- ffi_arg_setup(invoker, 1, &arg1, invoker->paramTypes, params, ffiValues);
409
- return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
674
+ return invoker_callN(self, 1, &arg1);
410
675
  }
411
676
 
412
677
  static VALUE
413
678
  invoker_call2(VALUE self, VALUE arg1, VALUE arg2)
414
679
  {
415
- Invoker* invoker;
416
- void* ffiValues[2];
417
- FFIStorage params[2];
418
680
  VALUE argv[] = { arg1, arg2 };
419
-
420
- Data_Get_Struct(self, Invoker, invoker);
421
- ffi_arg_setup(invoker, 2, argv, invoker->paramTypes, params, ffiValues);
422
- return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
681
+ return invoker_callN(self, 2, argv);
423
682
  }
424
683
 
425
684
  static VALUE
426
685
  invoker_call3(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3)
427
686
  {
428
- Invoker* invoker;
429
- void* ffiValues[3];
430
- FFIStorage params[3];
431
687
  VALUE argv[] = { arg1, arg2, arg3 };
688
+ return invoker_callN(self, 3, argv);
689
+ }
432
690
 
433
- Data_Get_Struct(self, Invoker, invoker);
434
- ffi_arg_setup(invoker, 3, argv, invoker->paramTypes, params, ffiValues);
435
- return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
691
+ #ifdef USE_RAW
692
+ static void
693
+ attached_method_invoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data)
694
+ {
695
+ MethodHandle* handle = (MethodHandle *) user_data;
696
+ Invoker* invoker = handle->invoker;
697
+ void* ffiValues[MAX_FIXED_ARITY];
698
+ FFIStorage params[MAX_FIXED_ARITY];
699
+
700
+ if (invoker->paramCount > 0) {
701
+ ffi_arg_setup(invoker, invoker->paramCount, (VALUE *)&parameters[1],
702
+ invoker->paramTypes, params, ffiValues);
703
+ }
704
+ *((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
705
+ }
706
+
707
+ static void
708
+ attached_method_vinvoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data)
709
+ {
710
+ MethodHandle* handle = (MethodHandle *) user_data;
711
+ Invoker* invoker = handle->invoker;
712
+ void** ffiValues = ALLOCA_N(void *, invoker->paramCount);
713
+ FFIStorage* params = ALLOCA_N(FFIStorage, invoker->paramCount);
714
+ int argc = parameters[0].sint;
715
+ VALUE* argv = *(VALUE **) &parameters[1];
716
+
717
+ ffi_arg_setup(invoker, argc, argv, invoker->paramTypes, params, ffiValues);
718
+ *((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
719
+ }
720
+
721
+ #else
722
+ #ifndef _WIN32
723
+ static void
724
+ attached_method_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
725
+ {
726
+ MethodHandle* handle = (MethodHandle *) user_data;
727
+ Invoker* invoker = handle->invoker;
728
+ void* ffiValues[MAX_FIXED_ARITY];
729
+ FFIStorage params[MAX_FIXED_ARITY];
730
+ VALUE argv[MAX_FIXED_ARITY];
731
+ int i;
732
+ //printf("Attached method invoke nargs=%d paramCount=%d\n", cif->nargs, invoker->paramCount); fflush(stdout);
733
+ for (i = 0; i < invoker->paramCount; ++i) {
734
+ memcpy(&argv[i], parameters[i + 1], sizeof(argv[i]));
735
+ }
736
+ if (invoker->paramCount > 0) {
737
+ ffi_arg_setup(invoker, invoker->paramCount, argv, invoker->paramTypes, params, ffiValues);
738
+ }
739
+ *((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
436
740
  }
741
+ #endif /* _WIN32 */
742
+ static void
743
+ attached_method_vinvoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
744
+ {
745
+ MethodHandle* handle = (MethodHandle *) user_data;
746
+ Invoker* invoker = handle->invoker;
747
+ void** ffiValues = ALLOCA_N(void *, invoker->paramCount);
748
+ FFIStorage* params = ALLOCA_N(FFIStorage, invoker->paramCount);
749
+ int argc = *(int *) parameters[0];
750
+ VALUE* argv = *(VALUE **) parameters[1];
437
751
 
752
+ ffi_arg_setup(invoker, argc, argv, invoker->paramTypes, params, ffiValues);
753
+ *((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
754
+ }
755
+ #endif
756
+ static VALUE
757
+ invoker_attach(VALUE self, VALUE module, VALUE name)
758
+ {
759
+ Invoker* invoker;
760
+ MethodHandle* handle;
761
+ char var[1024];
762
+ Data_Get_Struct(self, Invoker, invoker);
763
+ handle = invoker->methodHandle;
764
+ rb_define_module_function(module, StringValuePtr(name),
765
+ handle->code, handle->arity);
766
+ snprintf(var, sizeof(var), "@@%s", StringValueCStr(name));
767
+ rb_cv_set(module, var, self);
768
+ return self;
769
+ }
438
770
  static VALUE
439
771
  invoker_arity(VALUE self)
440
772
  {
@@ -470,6 +802,9 @@ invoker_free(Invoker *invoker)
470
802
  xfree(invoker->callbackParameters);
471
803
  invoker->callbackParameters = NULL;
472
804
  }
805
+ if (invoker->methodHandle != NULL) {
806
+ method_handle_free(invoker->methodHandle);
807
+ }
473
808
  xfree(invoker);
474
809
  }
475
810
  }
@@ -503,18 +838,18 @@ variadic_invoker_call(VALUE self, VALUE parameterTypes, VALUE parameterValues)
503
838
  VALUE entry = rb_ary_entry(parameterTypes, i);
504
839
  int paramType = FIX2INT(entry);
505
840
  switch (paramType) {
506
- case INT8:
507
- case INT16:
508
- case INT32:
509
- paramType = INT32;
841
+ case NATIVE_INT8:
842
+ case NATIVE_INT16:
843
+ case NATIVE_INT32:
844
+ paramType = NATIVE_INT32;
510
845
  break;
511
- case UINT8:
512
- case UINT16:
513
- case UINT32:
514
- paramType = UINT32;
846
+ case NATIVE_UINT8:
847
+ case NATIVE_UINT16:
848
+ case NATIVE_UINT32:
849
+ paramType = NATIVE_UINT32;
515
850
  break;
516
- case FLOAT32:
517
- paramType = FLOAT64;
851
+ case NATIVE_FLOAT32:
852
+ paramType = NATIVE_FLOAT64;
518
853
  break;
519
854
  }
520
855
  paramTypes[i] = paramType;
@@ -547,21 +882,15 @@ variadic_invoker_call(VALUE self, VALUE parameterTypes, VALUE parameterValues)
547
882
  static void*
548
883
  callback_param(VALUE proc, VALUE cbInfo)
549
884
  {
550
- VALUE callback;
551
- VALUE cbTable = RTEST(rb_ivar_defined(proc, cbTableID)) ? rb_ivar_get(proc, cbTableID) : Qnil;
552
- if (!cbTable || cbTable == Qnil) {
553
- cbTable = rb_hash_new();
554
- rb_ivar_set(proc, cbTableID, cbTable);
885
+ VALUE callback ;
886
+ if (proc == Qnil) {
887
+ return NULL ;
555
888
  }
556
- callback = rb_hash_aref(cbTable, cbInfo);
557
- if (callback != Qnil) {
558
- return ((NativeCallback *) DATA_PTR(callback))->code;
559
- }
560
- callback = rb_FFI_NativeCallback_new(cbInfo, proc);
561
- rb_hash_aset(cbTable, cbInfo, callback);
889
+ callback = rb_FFI_NativeCallback_for_proc(proc, cbInfo);
562
890
  return ((NativeCallback *) DATA_PTR(callback))->code;
563
891
  }
564
- #ifdef HAVE_NATIVETHREAD
892
+
893
+ #if defined(USE_PTHREAD_LOCAL)
565
894
  static ThreadData*
566
895
  thread_data_init()
567
896
  {
@@ -570,6 +899,7 @@ thread_data_init()
570
899
  pthread_setspecific(threadDataKey, td);
571
900
  return td;
572
901
  }
902
+
573
903
  static inline ThreadData*
574
904
  thread_data_get()
575
905
  {
@@ -582,13 +912,31 @@ thread_data_free(void *ptr)
582
912
  {
583
913
  xfree(ptr);
584
914
  }
585
- #else /* !HAVE_NATIVETHREAD */
586
- static ThreadData td0;
915
+
916
+ #else
917
+ static ID thread_data_id;
918
+
919
+ static ThreadData*
920
+ thread_data_init()
921
+ {
922
+ ThreadData* td;
923
+ VALUE obj;
924
+ obj = Data_Make_Struct(rb_cObject, ThreadData, NULL, -1, td);
925
+ rb_thread_local_aset(rb_thread_current(), thread_data_id, obj);
926
+ return td;
927
+ }
928
+
587
929
  static inline ThreadData*
588
930
  thread_data_get()
589
931
  {
590
- return &td0;
932
+ VALUE obj = rb_thread_local_aref(rb_thread_current(), thread_data_id);
933
+
934
+ if (obj != Qnil && TYPE(obj) == T_DATA) {
935
+ return (ThreadData *) DATA_PTR(obj);
936
+ }
937
+ return thread_data_init();
591
938
  }
939
+
592
940
  #endif
593
941
  static VALUE
594
942
  get_last_error(VALUE self)
@@ -604,25 +952,47 @@ set_last_error(VALUE self, VALUE error)
604
952
  void
605
953
  rb_FFI_Invoker_Init()
606
954
  {
955
+ ffi_type* ffiValueType;
956
+ int i;
607
957
  VALUE moduleFFI = rb_define_module("FFI");
608
958
  VALUE moduleError = rb_define_module_under(moduleFFI, "LastError");
609
959
  classInvoker = rb_define_class_under(moduleFFI, "Invoker", rb_cObject);
610
- rb_define_singleton_method(classInvoker, "new", invoker_new, 5);
960
+ rb_define_alloc_func(classInvoker, invoker_allocate);
961
+ rb_define_method(classInvoker, "initialize", invoker_initialize, 5);
611
962
  rb_define_method(classInvoker, "call", invoker_call, -1);
612
963
  rb_define_method(classInvoker, "call0", invoker_call0, 0);
613
964
  rb_define_method(classInvoker, "call1", invoker_call1, 1);
614
965
  rb_define_method(classInvoker, "call2", invoker_call2, 2);
615
966
  rb_define_method(classInvoker, "call3", invoker_call3, 3);
616
967
  rb_define_method(classInvoker, "arity", invoker_arity, 0);
968
+ rb_define_method(classInvoker, "attach", invoker_attach, 2);
617
969
  classVariadicInvoker = rb_define_class_under(moduleFFI, "VariadicInvoker", rb_cObject);
618
970
  rb_define_singleton_method(classVariadicInvoker, "__new", variadic_invoker_new, 4);
619
971
  rb_define_method(classVariadicInvoker, "invoke", variadic_invoker_call, 2);
620
- cbTableID = rb_intern("__ffi_callback_table__");
621
972
  to_ptr = rb_intern("to_ptr");
622
973
 
623
974
  rb_define_module_function(moduleError, "error", get_last_error, 0);
624
975
  rb_define_module_function(moduleError, "error=", set_last_error, 1);
625
- #ifdef HAVE_NATIVETHREAD
976
+
977
+ ffiValueType = (sizeof (VALUE) == sizeof (long))
978
+ ? &ffi_type_ulong : &ffi_type_uint64;
979
+ for (i = 0; i <= MAX_FIXED_ARITY + 1; ++i) {
980
+ methodHandleParamTypes[i] = ffiValueType;
981
+ }
982
+ methodHandleVarargParamTypes[2] = ffiValueType;
983
+
984
+ #ifndef _WIN32
985
+ PageSize = sysconf(_SC_PAGESIZE);
986
+ #endif /* _WIN32 */
987
+
988
+ #if defined(USE_PTHREAD_LOCAL)
626
989
  pthread_key_create(&threadDataKey, thread_data_free);
627
- #endif
990
+ for (i = 0; i < 4; ++i) {
991
+ pthread_mutex_init(&methodHandlePool[i].mutex, NULL);
992
+ }
993
+ pthread_mutex_init(&defaultMethodHandlePool.mutex, NULL);
994
+ #else
995
+ thread_data_id = rb_intern("ffi_thread_local_data");
996
+ #endif /* USE_PTHREAD_LOCAL */
997
+
628
998
  }