ffi 0.5.4-x86-mswin32 → 0.6.3-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.

Files changed (222) hide show
  1. data/History.txt +102 -0
  2. data/LICENSE +1 -27
  3. data/Rakefile +4 -12
  4. data/ext/ffi_c/AbstractMemory.c +6 -8
  5. data/ext/ffi_c/AbstractMemory.h +23 -21
  6. data/ext/ffi_c/AutoPointer.c +0 -1
  7. data/ext/ffi_c/Buffer.c +23 -8
  8. data/ext/ffi_c/Call.c +31 -3
  9. data/ext/ffi_c/Call.h +5 -1
  10. data/ext/ffi_c/DynamicLibrary.c +0 -1
  11. data/ext/ffi_c/Function.c +22 -4
  12. data/ext/ffi_c/MemoryPointer.c +2 -3
  13. data/ext/ffi_c/Pointer.c +23 -9
  14. data/ext/ffi_c/Struct.c +227 -79
  15. data/ext/ffi_c/Struct.h +16 -7
  16. data/ext/ffi_c/StructLayout.c +92 -55
  17. data/ext/ffi_c/Type.c +5 -22
  18. data/ext/ffi_c/Type.h +1 -1
  19. data/ext/ffi_c/Types.c +9 -3
  20. data/ext/ffi_c/Types.h +2 -0
  21. data/ext/ffi_c/extconf.rb +11 -7
  22. data/ext/ffi_c/libffi.gnu.mk +1 -1
  23. data/ext/ffi_c/libffi.mk +1 -1
  24. data/ext/ffi_c/libffi/ChangeLog +900 -84
  25. data/ext/ffi_c/libffi/ChangeLog.libffi +311 -0
  26. data/ext/ffi_c/libffi/LICENSE +1 -1
  27. data/ext/ffi_c/libffi/Makefile.am +14 -4
  28. data/ext/ffi_c/libffi/Makefile.in +362 -211
  29. data/ext/ffi_c/libffi/README +70 -92
  30. data/ext/ffi_c/libffi/aclocal.m4 +6068 -4586
  31. data/ext/ffi_c/libffi/config.guess +125 -143
  32. data/ext/ffi_c/libffi/config.sub +103 -27
  33. data/ext/ffi_c/libffi/configure +11340 -18473
  34. data/ext/ffi_c/libffi/configure.ac +43 -4
  35. data/ext/ffi_c/libffi/doc/libffi.info +15 -15
  36. data/ext/ffi_c/libffi/doc/libffi.texi +1 -1
  37. data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
  38. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  39. data/ext/ffi_c/libffi/fficonfig.h.in +24 -3
  40. data/ext/ffi_c/libffi/include/Makefile.am +1 -1
  41. data/ext/ffi_c/libffi/include/Makefile.in +97 -50
  42. data/ext/ffi_c/libffi/include/ffi.h.in +8 -2
  43. data/ext/ffi_c/libffi/include/ffi_common.h +24 -0
  44. data/ext/ffi_c/libffi/libtool-version +1 -1
  45. data/ext/ffi_c/libffi/ltmain.sh +7346 -5870
  46. data/ext/ffi_c/libffi/m4/libtool.m4 +7360 -0
  47. data/ext/ffi_c/libffi/m4/ltoptions.m4 +368 -0
  48. data/ext/ffi_c/libffi/m4/ltsugar.m4 +123 -0
  49. data/ext/ffi_c/libffi/m4/ltversion.m4 +23 -0
  50. data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +92 -0
  51. data/ext/ffi_c/libffi/man/Makefile.in +115 -62
  52. data/ext/ffi_c/libffi/man/ffi_call.3 +3 -3
  53. data/ext/ffi_c/libffi/missing +15 -8
  54. data/ext/ffi_c/libffi/src/arm/sysv.S +15 -8
  55. data/ext/ffi_c/libffi/src/avr32/ffi.c +421 -0
  56. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +50 -0
  57. data/ext/ffi_c/libffi/src/avr32/sysv.S +208 -0
  58. data/ext/ffi_c/libffi/src/closures.c +47 -10
  59. data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
  60. data/ext/ffi_c/libffi/src/java_raw_api.c +0 -3
  61. data/ext/ffi_c/libffi/src/mips/ffi.c +135 -32
  62. data/ext/ffi_c/libffi/src/mips/ffitarget.h +37 -4
  63. data/ext/ffi_c/libffi/src/mips/n32.S +67 -10
  64. data/ext/ffi_c/libffi/src/mips/o32.S +8 -8
  65. data/ext/ffi_c/libffi/src/pa/ffi.c +7 -0
  66. data/ext/ffi_c/libffi/src/powerpc/aix.S +163 -64
  67. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +308 -112
  68. data/ext/ffi_c/libffi/src/powerpc/ffi.c +20 -7
  69. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +208 -80
  70. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +11 -3
  71. data/ext/ffi_c/libffi/src/powerpc/sysv.S +12 -23
  72. data/ext/ffi_c/libffi/src/s390/sysv.S +1 -1
  73. data/ext/ffi_c/libffi/src/sh/sysv.S +9 -9
  74. data/ext/ffi_c/libffi/src/sh64/ffi.c +37 -22
  75. data/ext/ffi_c/libffi/src/sh64/sysv.S +23 -14
  76. data/ext/ffi_c/libffi/src/sparc/ffi.c +21 -6
  77. data/ext/ffi_c/libffi/src/sparc/v8.S +55 -14
  78. data/ext/ffi_c/libffi/src/x86/darwin.S +10 -9
  79. data/ext/ffi_c/libffi/src/x86/ffi.c +293 -86
  80. data/ext/ffi_c/libffi/src/x86/ffi64.c +73 -19
  81. data/ext/ffi_c/libffi/src/x86/ffitarget.h +30 -0
  82. data/ext/ffi_c/libffi/src/x86/sysv.S +21 -4
  83. data/ext/ffi_c/libffi/src/x86/unix64.S +8 -4
  84. data/ext/ffi_c/libffi/src/x86/win32.S +633 -147
  85. data/ext/ffi_c/libffi/src/x86/win64.S +460 -0
  86. data/ext/ffi_c/libffi/testsuite/Makefile.am +63 -54
  87. data/ext/ffi_c/libffi/testsuite/Makefile.in +112 -77
  88. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +12 -1
  89. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +4 -4
  90. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +7 -15
  91. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +7 -15
  92. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +7 -15
  93. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +7 -15
  94. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +7 -15
  95. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +7 -14
  96. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +7 -15
  97. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_loc_fn0.c +95 -0
  98. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +6 -14
  99. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +4 -12
  100. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +4 -12
  101. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +4 -12
  102. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +4 -12
  103. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +4 -12
  104. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +4 -12
  105. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +4 -12
  106. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +4 -12
  107. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +4 -12
  108. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +4 -12
  109. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +4 -12
  110. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +4 -12
  111. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +4 -12
  112. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +4 -12
  113. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +4 -12
  114. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +4 -12
  115. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +4 -12
  116. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +4 -12
  117. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +4 -12
  118. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +4 -12
  119. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +4 -12
  120. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +4 -12
  121. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +4 -12
  122. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +4 -12
  123. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +4 -12
  124. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +4 -12
  125. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +4 -12
  126. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +134 -0
  127. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +117 -0
  128. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +11 -17
  129. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +4 -12
  130. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +4 -12
  131. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +7 -15
  132. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +4 -12
  133. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +4 -12
  134. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +7 -15
  135. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +66 -0
  136. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +4 -12
  137. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +57 -0
  138. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +4 -13
  139. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +105 -0
  140. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +57 -0
  141. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +4 -12
  142. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +4 -12
  143. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +4 -12
  144. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +4 -12
  145. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +4 -12
  146. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +4 -12
  147. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +74 -0
  148. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +140 -0
  149. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +4 -12
  150. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +4 -12
  151. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +4 -12
  152. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +4 -12
  153. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +4 -12
  154. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +8 -16
  155. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +4 -12
  156. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +37 -0
  157. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +25 -0
  158. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +31 -0
  159. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +2 -1
  160. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +342 -0
  161. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +4 -12
  162. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +4 -12
  163. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +4 -12
  164. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +4 -12
  165. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +4 -12
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +4 -12
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +4 -12
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +4 -12
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +4 -12
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +4 -12
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +4 -12
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +4 -12
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +1 -1
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -1
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large.c +145 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +148 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +124 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +124 -0
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/testclosure.c +70 -0
  180. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +10 -0
  181. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +4 -5
  182. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +17 -16
  183. data/ext/ffi_c/libffi/texinfo.tex +155 -427
  184. data/gen/Rakefile +4 -2
  185. data/lib/1.8/ffi_c.so +0 -0
  186. data/lib/1.9/ffi_c.so +0 -0
  187. data/lib/ffi/autopointer.rb +79 -20
  188. data/lib/ffi/callback.rb +4 -10
  189. data/lib/ffi/enum.rb +28 -0
  190. data/lib/ffi/ffi.rb +1 -0
  191. data/lib/ffi/io.rb +28 -0
  192. data/lib/ffi/library.rb +237 -182
  193. data/lib/ffi/memorypointer.rb +28 -62
  194. data/lib/ffi/platform.rb +27 -0
  195. data/lib/ffi/pointer.rb +28 -0
  196. data/lib/ffi/struct.rb +55 -1
  197. data/lib/ffi/types.rb +29 -0
  198. data/lib/ffi/variadic.rb +29 -0
  199. data/spec/ffi/library_spec.rb +31 -5
  200. data/spec/ffi/rbx/attach_function_spec.rb +2 -1
  201. data/spec/ffi/rbx/memory_pointer_spec.rb +2 -1
  202. data/spec/ffi/spec_helper.rb +5 -1
  203. data/spec/ffi/struct_spec.rb +82 -0
  204. data/tasks/ann.rake +80 -0
  205. data/tasks/extension.rake +25 -0
  206. data/tasks/gem.rake +200 -0
  207. data/tasks/git.rake +41 -0
  208. data/tasks/notes.rake +27 -0
  209. data/tasks/post_load.rake +34 -0
  210. data/tasks/rdoc.rake +50 -0
  211. data/tasks/rubyforge.rake +55 -0
  212. data/tasks/setup.rb +300 -0
  213. data/tasks/spec.rake +54 -0
  214. data/tasks/svn.rake +47 -0
  215. data/tasks/test.rake +40 -0
  216. metadata +312 -279
  217. data/ext/ffi_c/libffi/TODO +0 -1
  218. data/ext/ffi_c/libffi/ltcf-c.sh +0 -861
  219. data/ext/ffi_c/libffi/ltcf-cxx.sh +0 -1069
  220. data/ext/ffi_c/libffi/ltcf-gcj.sh +0 -700
  221. data/ext/ffi_c/libffi/ltconfig +0 -2862
  222. data/ext/ffi_c/libffi/mkinstalldirs +0 -158
@@ -35,7 +35,9 @@
35
35
  extern "C" {
36
36
  #endif
37
37
 
38
- #if defined(__i386__) && defined(HAVE_RAW_API) && !defined(_WIN32) && !defined(__WIN32__)
38
+ #if defined(__i386__) && \
39
+ (defined(HAVE_RAW_API) || defined(USE_INTERNAL_LIBFFI)) && \
40
+ !defined(_WIN32) && !defined(__WIN32__)
39
41
  # define USE_RAW
40
42
  #endif
41
43
 
@@ -57,6 +59,8 @@ typedef union {
57
59
  #endif
58
60
  signed long long i64;
59
61
  unsigned long long u64;
62
+ signed long sl;
63
+ unsigned long ul;
60
64
  void* ptr;
61
65
  float f32;
62
66
  double f64;
@@ -157,7 +157,6 @@ symbol_new(VALUE library, void* address, VALUE name)
157
157
  sym->memory.size = LONG_MAX;
158
158
  sym->memory.typeSize = 1;
159
159
  sym->memory.access = MEM_RD | MEM_WR;
160
- sym->memory.ops = &rbffi_AbstractMemoryOps;
161
160
  sym->library = library;
162
161
  sym->name = name;
163
162
 
@@ -81,7 +81,6 @@ function_allocate(VALUE klass)
81
81
  obj = Data_Make_Struct(klass, Function, function_mark, function_free, fn);
82
82
 
83
83
  fn->memory.access = MEM_RD;
84
- fn->memory.ops = &rbffi_AbstractMemoryOps;
85
84
 
86
85
  fn->rbProc = Qnil;
87
86
  fn->rbFunctionInfo = Qnil;
@@ -250,7 +249,13 @@ function_attach(VALUE self, VALUE module, VALUE name)
250
249
  Data_Get_Struct(self, Function, fn);
251
250
 
252
251
  if (fn->info->parameterCount == -1) {
253
- rb_raise(rb_eRuntimeError, "Cannot attach variadic functions");
252
+ rb_raise(rb_eRuntimeError, "cannot attach variadic functions");
253
+ return Qnil;
254
+ }
255
+
256
+ if (!rb_obj_is_kind_of(module, rb_cModule)) {
257
+ rb_raise(rb_eRuntimeError, "trying to attach function to non-module");
258
+ return Qnil;
254
259
  }
255
260
 
256
261
  if (fn->methodHandle == NULL) {
@@ -350,6 +355,12 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
350
355
  case NATIVE_UINT64:
351
356
  param = ULL2NUM(*(uint64_t *) parameters[i]);
352
357
  break;
358
+ case NATIVE_LONG:
359
+ param = LONG2NUM(*(long *) parameters[i]);
360
+ break;
361
+ case NATIVE_ULONG:
362
+ param = ULONG2NUM(*(unsigned long *) parameters[i]);
363
+ break;
353
364
  case NATIVE_FLOAT32:
354
365
  param = rb_float_new(*(float *) parameters[i]);
355
366
  break;
@@ -363,7 +374,7 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
363
374
  param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
364
375
  break;
365
376
  case NATIVE_BOOL:
366
- param = (*(void **) parameters[i]) ? Qtrue : Qfalse;
377
+ param = (*(uint8_t *) parameters[i]) ? Qtrue : Qfalse;
367
378
  break;
368
379
 
369
380
  case NATIVE_FUNCTION:
@@ -397,6 +408,12 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
397
408
  case NATIVE_UINT64:
398
409
  *((uint64_t *) retval) = NUM2ULL(rbReturnValue);
399
410
  break;
411
+ case NATIVE_LONG:
412
+ *((ffi_sarg *) retval) = NUM2LONG(rbReturnValue);
413
+ break;
414
+ case NATIVE_ULONG:
415
+ *((ffi_arg *) retval) = NUM2ULONG(rbReturnValue);
416
+ break;
400
417
  case NATIVE_FLOAT32:
401
418
  *((float *) retval) = (float) NUM2DBL(rbReturnValue);
402
419
  break;
@@ -411,8 +428,9 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
411
428
  *((void **) retval) = NULL;
412
429
  }
413
430
  break;
431
+
414
432
  case NATIVE_BOOL:
415
- *((ffi_sarg *) retval) = TYPE(rbReturnValue) == T_TRUE ? 1 : 0;
433
+ *((ffi_arg *) retval) = rbReturnValue == Qtrue;
416
434
  break;
417
435
 
418
436
  case NATIVE_FUNCTION:
@@ -63,7 +63,6 @@ memptr_allocate(VALUE klass)
63
63
  {
64
64
  MemoryPointer* p;
65
65
  VALUE obj = Data_Make_Struct(klass, MemoryPointer, NULL, memptr_release, p);
66
- p->memory.ops = &rbffi_AbstractMemoryOps;
67
66
  p->memory.access = MEM_RD | MEM_WR;
68
67
 
69
68
  return obj;
@@ -106,7 +105,7 @@ memptr_malloc(VALUE self, long size, long count, bool clear)
106
105
  /* ensure the memory is aligned on at least a 8 byte boundary */
107
106
  p->memory.address = (char *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);;
108
107
  p->allocated = true;
109
-
108
+
110
109
  if (clear && p->memory.size > 0) {
111
110
  memset(p->memory.address, 0, p->memory.size);
112
111
  }
@@ -135,7 +134,7 @@ memptr_free(VALUE self)
135
134
 
136
135
  if (ptr->allocated) {
137
136
  if (ptr->storage != NULL) {
138
- free(ptr->storage);
137
+ xfree(ptr->storage);
139
138
  ptr->storage = NULL;
140
139
  }
141
140
  ptr->allocated = false;
@@ -59,7 +59,6 @@ rbffi_Pointer_NewInstance(void* addr)
59
59
  obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
60
60
  p->memory.address = addr;
61
61
  p->memory.size = LONG_MAX;
62
- p->memory.ops = &rbffi_AbstractMemoryOps;
63
62
  p->memory.access = (addr == NULL) ? 0 : (MEM_RD | MEM_WR);
64
63
  p->memory.typeSize = 1;
65
64
  p->parent = Qnil;
@@ -75,7 +74,6 @@ ptr_allocate(VALUE klass)
75
74
 
76
75
  obj = Data_Make_Struct(klass, Pointer, NULL, -1, p);
77
76
  p->parent = Qnil;
78
- p->memory.ops = &rbffi_AbstractMemoryOps;
79
77
  p->memory.access = MEM_RD | MEM_WR;
80
78
 
81
79
  return obj;
@@ -132,21 +130,19 @@ ptr_initialize(int argc, VALUE* argv, VALUE self)
132
130
 
133
131
 
134
132
  static VALUE
135
- ptr_plus(VALUE self, VALUE offset)
133
+ slice(VALUE self, long offset, long size)
136
134
  {
137
135
  AbstractMemory* ptr;
138
136
  Pointer* p;
139
137
  VALUE retval;
140
- long off = NUM2LONG(offset);
141
-
138
+
142
139
  Data_Get_Struct(self, AbstractMemory, ptr);
143
- checkBounds(ptr, off, 1);
140
+ checkBounds(ptr, offset, 1);
144
141
 
145
142
  retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p);
146
143
 
147
- p->memory.address = ptr->address + off;
148
- p->memory.size = ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off;
149
- p->memory.ops = &rbffi_AbstractMemoryOps;
144
+ p->memory.address = ptr->address + offset;
145
+ p->memory.size = size;
150
146
  p->memory.access = ptr->access;
151
147
  p->memory.typeSize = ptr->typeSize;
152
148
  p->parent = self;
@@ -154,6 +150,23 @@ ptr_plus(VALUE self, VALUE offset)
154
150
  return retval;
155
151
  }
156
152
 
153
+ static VALUE
154
+ ptr_plus(VALUE self, VALUE offset)
155
+ {
156
+ AbstractMemory* ptr;
157
+ long off = NUM2LONG(offset);
158
+
159
+ Data_Get_Struct(self, AbstractMemory, ptr);
160
+
161
+ return slice(self, off, ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off);
162
+ }
163
+
164
+ static VALUE
165
+ ptr_slice(VALUE self, VALUE rbOffset, VALUE rbLength)
166
+ {
167
+ return slice(self, NUM2LONG(rbOffset), NUM2LONG(rbLength));
168
+ }
169
+
157
170
  static VALUE
158
171
  ptr_inspect(VALUE self)
159
172
  {
@@ -214,6 +227,7 @@ rbffi_Pointer_Init(VALUE moduleFFI)
214
227
  rb_define_method(rbffi_PointerClass, "initialize", ptr_initialize, -1);
215
228
  rb_define_method(rbffi_PointerClass, "inspect", ptr_inspect, 0);
216
229
  rb_define_method(rbffi_PointerClass, "+", ptr_plus, 1);
230
+ rb_define_method(rbffi_PointerClass, "slice", ptr_slice, 2);
217
231
  rb_define_method(rbffi_PointerClass, "null?", ptr_null_p, 0);
218
232
  rb_define_method(rbffi_PointerClass, "address", ptr_address, 0);
219
233
  rb_define_alias(rbffi_PointerClass, "to_i", "address");
@@ -63,12 +63,16 @@ typedef struct InlineArray_ {
63
63
  StructField* field;
64
64
  MemoryOp *op;
65
65
  Type* componentType;
66
+ ArrayType* arrayType;
67
+ unsigned int length;
66
68
  } InlineArray;
67
69
 
68
70
 
69
71
  static void struct_mark(Struct *);
70
72
  static void struct_layout_builder_mark(StructLayoutBuilder *);
71
73
  static void struct_layout_builder_free(StructLayoutBuilder *);
74
+ static VALUE struct_class_layout(VALUE klass);
75
+ static void struct_malloc(Struct* s);
72
76
  static void inline_array_mark(InlineArray *);
73
77
 
74
78
  static inline int align(int offset, int align);
@@ -77,6 +81,8 @@ VALUE rbffi_StructClass = Qnil;
77
81
  static VALUE StructLayoutBuilderClass = Qnil;
78
82
 
79
83
  VALUE rbffi_StructInlineArrayClass = Qnil;
84
+ VALUE rbffi_StructLayoutCharArrayClass = Qnil;
85
+
80
86
  static ID id_pointer_ivar = 0, id_layout_ivar = 0;
81
87
  static ID id_get = 0, id_put = 0, id_to_ptr = 0, id_to_s = 0, id_layout = 0;
82
88
 
@@ -112,10 +118,8 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
112
118
  /* Call up into ruby code to adjust the layout */
113
119
  if (nargs > 1) {
114
120
  s->rbLayout = rb_funcall2(CLASS_OF(self), id_layout, RARRAY_LEN(rest), RARRAY_PTR(rest));
115
- } else if (rb_cvar_defined(klass, id_layout_ivar)) {
116
- s->rbLayout = rb_cvar_get(klass, id_layout_ivar);
117
121
  } else {
118
- rb_raise(rb_eRuntimeError, "No Struct layout configured");
122
+ s->rbLayout = struct_class_layout(klass);
119
123
  }
120
124
 
121
125
  if (!rb_obj_is_kind_of(s->rbLayout, rbffi_StructLayoutClass)) {
@@ -128,16 +132,72 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
128
132
  s->pointer = MEMORY(rbPointer);
129
133
  s->rbPointer = rbPointer;
130
134
  } else {
131
- s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
132
- s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
135
+ struct_malloc(s);
136
+ }
137
+
138
+ return self;
139
+ }
140
+
141
+ static VALUE
142
+ struct_class_layout(VALUE klass)
143
+ {
144
+ VALUE layout;
145
+ if (!rb_cvar_defined(klass, id_layout_ivar)) {
146
+ rb_raise(rb_eRuntimeError, "no Struct layout configured for %s", rb_class2name(klass));
133
147
  }
134
148
 
135
- if (s->pointer->ops == NULL) {
136
- VALUE name = rb_class_name(CLASS_OF(s->rbPointer));
137
- rb_raise(rb_eRuntimeError, "No memory ops set for %s", StringValueCStr(name));
149
+ layout = rb_cvar_get(klass, id_layout_ivar);
150
+ if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
151
+ rb_raise(rb_eRuntimeError, "invalid Struct layout for %s", rb_class2name(klass));
138
152
  }
139
153
 
140
- return self;
154
+ return layout;
155
+ }
156
+
157
+ static StructLayout*
158
+ struct_layout(VALUE self)
159
+ {
160
+ Struct* s = (Struct *) DATA_PTR(self);
161
+ if (s->layout != NULL) {
162
+ return s->layout;
163
+ }
164
+
165
+ if (s->layout == NULL) {
166
+ s->rbLayout = struct_class_layout(CLASS_OF(self));
167
+ Data_Get_Struct(s->rbLayout, StructLayout, s->layout);
168
+ }
169
+
170
+ return s->layout;
171
+ }
172
+
173
+ static Struct*
174
+ struct_validate(VALUE self)
175
+ {
176
+ Struct* s;
177
+ Data_Get_Struct(self, Struct, s);
178
+
179
+ if (struct_layout(self) == NULL) {
180
+ rb_raise(rb_eRuntimeError, "struct layout == null");
181
+ }
182
+
183
+ if (s->pointer == NULL) {
184
+ struct_malloc(s);
185
+ }
186
+
187
+ return s;
188
+ }
189
+
190
+ static void
191
+ struct_malloc(Struct* s)
192
+ {
193
+ if (s->rbPointer == Qnil) {
194
+ s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
195
+
196
+ } else if (!rb_obj_is_kind_of(s->rbPointer, rbffi_AbstractMemoryClass)) {
197
+ rb_raise(rb_eRuntimeError, "invalid pointer in struct");
198
+ }
199
+
200
+ s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
141
201
  }
142
202
 
143
203
  static void
@@ -152,9 +212,6 @@ struct_field(Struct* s, VALUE fieldName)
152
212
  {
153
213
  StructLayout* layout = s->layout;
154
214
  VALUE rbField;
155
- if (layout == NULL) {
156
- rb_raise(rb_eRuntimeError, "layout not set for Struct");
157
- }
158
215
 
159
216
  rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
160
217
  if (rbField == Qnil) {
@@ -171,19 +228,23 @@ struct_aref(VALUE self, VALUE fieldName)
171
228
  Struct* s;
172
229
  VALUE rbField;
173
230
  StructField* f;
174
- MemoryOp* op;
175
231
 
176
- Data_Get_Struct(self, Struct, s);
232
+ s = struct_validate(self);
233
+
177
234
  rbField = struct_field(s, fieldName);
178
235
  f = (StructField *) DATA_PTR(rbField);
179
236
 
180
- op = memory_get_op(s->pointer, f->type);
181
- if (op != NULL) {
182
- return (*op->get)(s->pointer, f->offset);
183
- }
237
+ if (f->get != NULL) {
238
+ return (*f->get)(f, s);
239
+
240
+ } else if (f->memoryOp != NULL) {
241
+ return (*f->memoryOp->get)(s->pointer, f->offset);
242
+
243
+ } else {
184
244
 
185
- /* call up to the ruby code to fetch the value */
186
- return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
245
+ /* call up to the ruby code to fetch the value */
246
+ return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
247
+ }
187
248
  }
188
249
 
189
250
  static VALUE
@@ -192,37 +253,53 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
192
253
  Struct* s;
193
254
  VALUE rbField;
194
255
  StructField* f;
195
- MemoryOp* op;
196
- VALUE argv[2];
197
256
 
198
- Data_Get_Struct(self, Struct, s);
257
+
258
+ s = struct_validate(self);
259
+
199
260
  rbField = struct_field(s, fieldName);
200
261
  f = (StructField *) DATA_PTR(rbField);
262
+ if (f->put != NULL) {
263
+ (*f->put)(f, s, value);
201
264
 
202
- op = memory_get_op(s->pointer, f->type);
203
- if (op != NULL) {
204
- (*op->put)(s->pointer, f->offset, value);
205
- return self;
206
- }
265
+ } else if (f->memoryOp != NULL) {
266
+
267
+ (*f->memoryOp->put)(s->pointer, f->offset, value);
207
268
 
208
- /* call up to the ruby code to set the value */
209
- argv[0] = s->rbPointer;
210
- argv[1] = value;
211
- rb_funcall2(rbField, id_put, 2, argv);
269
+ } else {
270
+ /* call up to the ruby code to set the value */
271
+ VALUE argv[2];
272
+ argv[0] = s->rbPointer;
273
+ argv[1] = value;
274
+ rb_funcall2(rbField, id_put, 2, argv);
275
+ }
212
276
 
213
- return self;
277
+ return value;
214
278
  }
215
279
 
216
280
  static VALUE
217
281
  struct_set_pointer(VALUE self, VALUE pointer)
218
282
  {
219
283
  Struct* s;
284
+ StructLayout* layout;
285
+ AbstractMemory* memory;
220
286
 
221
287
  if (!rb_obj_is_kind_of(pointer, rbffi_AbstractMemoryClass)) {
222
- rb_raise(rb_eArgError, "Invalid pointer");
288
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Pointer or Buffer)",
289
+ rb_obj_classname(pointer));
290
+ return Qnil;
223
291
  }
224
292
 
293
+
225
294
  Data_Get_Struct(self, Struct, s);
295
+ Data_Get_Struct(pointer, AbstractMemory, memory);
296
+ layout = struct_layout(self);
297
+
298
+ if (layout->base.ffiType->size > memory->size) {
299
+ rb_raise(rb_eArgError, "memory of %d bytes too small for struct %s (expected at least %d)",
300
+ memory->size, rb_obj_classname(self), layout->base.ffiType->size);
301
+ }
302
+
226
303
  s->pointer = MEMORY(pointer);
227
304
  s->rbPointer = pointer;
228
305
  rb_ivar_set(self, id_pointer_ivar, pointer);
@@ -247,7 +324,9 @@ struct_set_layout(VALUE self, VALUE layout)
247
324
  Data_Get_Struct(self, Struct, s);
248
325
 
249
326
  if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
250
- rb_raise(rb_eArgError, "Invalid Struct layout");
327
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
328
+ rb_obj_classname(layout), rb_class2name(rbffi_StructLayoutClass));
329
+ return Qnil;
251
330
  }
252
331
 
253
332
  Data_Get_Struct(layout, StructLayout, s->layout);
@@ -425,16 +504,32 @@ struct_layout_builder_add_field(int argc, VALUE* argv, VALUE self)
425
504
  fargv[0] = rbName;
426
505
  fargv[1] = UINT2NUM(offset);
427
506
  fargv[2] = rbType;
507
+
428
508
  if (rb_obj_is_kind_of(rbType, rbffi_FunctionTypeClass)) {
509
+
429
510
  rbFieldClass = rbffi_StructLayoutFunctionFieldClass;
511
+
430
512
  } else if (rb_obj_is_kind_of(rbType, rbffi_StructByValueClass)) {
431
- rbFieldClass = rbffi_StructLayoutStructFieldClass;
513
+
514
+ rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
515
+
432
516
  } else if (rb_obj_is_kind_of(rbType, rbffi_ArrayTypeClass)) {
517
+
433
518
  rbFieldClass = rbffi_StructLayoutArrayFieldClass;
519
+
520
+ } else if (rb_obj_is_kind_of(rbType, rbffi_EnumTypeClass)) {
521
+
522
+ rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("Enum"));
523
+
434
524
  } else {
435
525
  rbFieldClass = rbffi_StructLayoutFieldClass;
436
526
  }
437
527
 
528
+ if (!RTEST(rbFieldClass)) {
529
+ rb_raise(rb_eTypeError, "invalid struct field type (%s)", rb_obj_classname(rbType));
530
+ return Qnil;
531
+ }
532
+
438
533
  rbField = rb_class_new_instance(3, fargv, rbFieldClass);
439
534
  } else {
440
535
  rbField = rbType;
@@ -449,7 +544,8 @@ static VALUE
449
544
  struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
450
545
  {
451
546
  StructLayoutBuilder* builder;
452
- VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil, rbStructClass = Qnil;
547
+ VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
548
+ VALUE rbFieldClass = Qnil, rbStructClass = Qnil;
453
549
  VALUE fargv[3];
454
550
  unsigned int size, alignment, offset;
455
551
  int nargs;
@@ -472,7 +568,14 @@ struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
472
568
  fargv[0] = rbName;
473
569
  fargv[1] = UINT2NUM(offset);
474
570
  fargv[2] = rbType;
475
- rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutStructFieldClass);
571
+ rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
572
+ if (!RTEST(rbFieldClass)) {
573
+ rb_raise(rb_eRuntimeError, "could not locate StructLayout::InlineStruct");
574
+ return Qnil;
575
+ }
576
+
577
+ rbField = rb_class_new_instance(3, fargv, rbFieldClass);
578
+
476
579
  store_field(builder, rbName, rbField, offset, size, alignment);
477
580
 
478
581
  return self;
@@ -554,21 +657,18 @@ static VALUE
554
657
  inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
555
658
  {
556
659
  InlineArray* array;
557
- ArrayType* arrayType;
558
-
660
+
559
661
  Data_Get_Struct(self, InlineArray, array);
560
662
  array->rbMemory = rbMemory;
561
663
  array->rbField = rbField;
562
664
 
563
665
  Data_Get_Struct(rbMemory, AbstractMemory, array->memory);
564
666
  Data_Get_Struct(rbField, StructField, array->field);
565
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
566
- Data_Get_Struct(arrayType->rbComponentType, Type, array->componentType);
667
+ Data_Get_Struct(array->field->rbType, ArrayType, array->arrayType);
668
+ Data_Get_Struct(array->arrayType->rbComponentType, Type, array->componentType);
567
669
 
568
- array->op = memory_get_op(array->memory, array->componentType);
569
- if (array->op == NULL) {
570
- rb_raise(rb_eRuntimeError, "invalid memory ops");
571
- }
670
+ array->op = get_memory_op(array->componentType);
671
+ array->length = array->arrayType->length;
572
672
 
573
673
  return self;
574
674
  }
@@ -584,8 +684,12 @@ inline_array_size(VALUE self)
584
684
  }
585
685
 
586
686
  static int
587
- inline_array_offset(InlineArray* array, unsigned int index)
687
+ inline_array_offset(InlineArray* array, int index)
588
688
  {
689
+ if (index < 0 || index >= array->length) {
690
+ rb_raise(rb_eIndexError, "index %d out of bounds", index);
691
+ }
692
+
589
693
  return array->field->offset + (index * array->componentType->ffiType->size);
590
694
  }
591
695
 
@@ -596,7 +700,19 @@ inline_array_aref(VALUE self, VALUE rbIndex)
596
700
 
597
701
  Data_Get_Struct(self, InlineArray, array);
598
702
 
599
- return array->op->get(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)));
703
+ if (array->op != NULL) {
704
+ return array->op->get(array->memory, inline_array_offset(array, NUM2INT(rbIndex)));
705
+ } else if (array->componentType->nativeType == NATIVE_STRUCT) {
706
+ VALUE rbOffset = INT2NUM(inline_array_offset(array, NUM2INT(rbIndex)));
707
+ VALUE rbLength = INT2NUM(array->componentType->ffiType->size);
708
+ VALUE rbPointer = rb_funcall(array->rbMemory, rb_intern("slice"), 2, rbOffset, rbLength);
709
+
710
+ return rb_class_new_instance(1, &rbPointer, ((StructByValue *) array->componentType)->rbStructClass);
711
+ } else {
712
+
713
+ rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(array->arrayType->rbComponentType));
714
+ return Qnil;
715
+ }
600
716
  }
601
717
 
602
718
  static VALUE
@@ -606,8 +722,34 @@ inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
606
722
 
607
723
  Data_Get_Struct(self, InlineArray, array);
608
724
 
609
- array->op->put(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)),
610
- rbValue);
725
+ if (array->op != NULL) {
726
+ array->op->put(array->memory, inline_array_offset(array, NUM2INT(rbIndex)),
727
+ rbValue);
728
+ } else if (array->componentType->nativeType == NATIVE_STRUCT) {
729
+ int offset = inline_array_offset(array, NUM2INT(rbIndex));
730
+ Struct* s;
731
+
732
+ if (!rb_obj_is_kind_of(rbValue, rbffi_StructClass)) {
733
+ rb_raise(rb_eTypeError, "argument not an instance of struct");
734
+ return Qnil;
735
+ }
736
+
737
+ checkWrite(array->memory);
738
+ checkBounds(array->memory, offset, array->componentType->ffiType->size);
739
+
740
+ Data_Get_Struct(rbValue, Struct, s);
741
+ checkRead(s->pointer);
742
+ checkBounds(s->pointer, 0, array->componentType->ffiType->size);
743
+
744
+ memcpy(array->memory->address + offset, s->pointer->address, array->componentType->ffiType->size);
745
+
746
+ } else {
747
+ ArrayType* arrayType;
748
+ Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
749
+
750
+ rb_raise(rb_eArgError, "set not supported for %s", rb_obj_classname(arrayType->rbComponentType));
751
+ return Qnil;
752
+ }
611
753
 
612
754
  return rbValue;
613
755
  }
@@ -616,16 +758,30 @@ static VALUE
616
758
  inline_array_each(VALUE self)
617
759
  {
618
760
  InlineArray* array;
619
- ArrayType* arrayType;
620
761
 
621
762
  int i;
622
763
 
623
764
  Data_Get_Struct(self, InlineArray, array);
624
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
765
+
766
+ if (array->op != NULL) {
767
+ for (i = 0; i < array->length; ++i) {
768
+ int offset = inline_array_offset(array, i);
769
+ rb_yield(array->op->get(array->memory, offset));
770
+ }
771
+ } else if (array->componentType->nativeType == NATIVE_STRUCT) {
772
+ for (i = 0; i < array->length; ++i) {
773
+ VALUE rbOffset = UINT2NUM(inline_array_offset(array, i));
774
+ VALUE rbLength = UINT2NUM(array->componentType->ffiType->size);
775
+ VALUE rbPointer = rb_funcall(array->rbMemory, rb_intern("slice"), 2, rbOffset, rbLength);
776
+
777
+ rb_yield(rb_class_new_instance(1, &rbPointer, ((StructByValue *) array->componentType)->rbStructClass));
778
+ }
779
+ } else {
780
+ ArrayType* arrayType;
781
+ Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
625
782
 
626
- for (i = 0; i < arrayType->length; ++i) {
627
- int offset = inline_array_offset(array, i);
628
- rb_yield(array->op->get(array->memory, offset));
783
+ rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(arrayType->rbComponentType));
784
+ return Qnil;
629
785
  }
630
786
 
631
787
  return self;
@@ -635,16 +791,14 @@ static VALUE
635
791
  inline_array_to_a(VALUE self)
636
792
  {
637
793
  InlineArray* array;
638
- ArrayType* arrayType;
639
794
  VALUE obj;
640
795
  int i;
641
796
 
642
797
  Data_Get_Struct(self, InlineArray, array);
643
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
644
- obj = rb_ary_new2(arrayType->length);
798
+ obj = rb_ary_new2(array->length);
645
799
 
646
800
 
647
- for (i = 0; i < arrayType->length; ++i) {
801
+ for (i = 0; i < array->length; ++i) {
648
802
  int offset = inline_array_offset(array, i);
649
803
  rb_ary_push(obj, array->op->get(array->memory, offset));
650
804
  }
@@ -656,19 +810,17 @@ static VALUE
656
810
  inline_array_to_s(VALUE self)
657
811
  {
658
812
  InlineArray* array;
659
- ArrayType* arrayType;
660
813
  VALUE argv[2];
661
814
 
662
815
  Data_Get_Struct(self, InlineArray, array);
663
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
664
-
665
- if (arrayType->componentType->nativeType != NATIVE_INT8 && arrayType->componentType->nativeType != NATIVE_UINT8) {
666
- rb_raise(rb_eNoMethodError, "to_s not defined for this array type");
667
- return Qnil;
816
+
817
+ if (array->componentType->nativeType != NATIVE_INT8 && array->componentType->nativeType != NATIVE_UINT8) {
818
+ VALUE dummy = Qnil;
819
+ return rb_call_super(0, &dummy);
668
820
  }
669
821
 
670
822
  argv[0] = UINT2NUM(array->field->offset);
671
- argv[1] = UINT2NUM(arrayType->length);
823
+ argv[1] = UINT2NUM(array->length);
672
824
 
673
825
  return rb_funcall2(array->rbMemory, rb_intern("get_string"), 2, argv);
674
826
  }
@@ -678,19 +830,11 @@ static VALUE
678
830
  inline_array_to_ptr(VALUE self)
679
831
  {
680
832
  InlineArray* array;
681
- AbstractMemory* ptr;
682
- VALUE rbOffset, rbPointer;
683
-
684
- Data_Get_Struct(self, InlineArray, array);
685
-
686
- rbOffset = UINT2NUM(array->field->offset);
687
- rbPointer = rb_funcall2(array->rbMemory, rb_intern("+"), 1, &rbOffset);
688
- Data_Get_Struct(rbPointer, AbstractMemory, ptr);
689
833
 
690
- // Restrict the size of the pointer so ops like ptr.get_string(0) are bounds checked
691
- ptr->size = MIN(ptr->size, array->field->type->ffiType->size);
834
+ Data_Get_Struct(self, InlineArray, array);
692
835
 
693
- return rbPointer;
836
+ return rb_funcall(array->rbMemory, rb_intern("slice"), 2,
837
+ UINT2NUM(array->field->offset), UINT2NUM(array->arrayType->base.ffiType->size));
694
838
  }
695
839
 
696
840
 
@@ -711,6 +855,9 @@ rbffi_Struct_Init(VALUE moduleFFI)
711
855
  rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
712
856
  rb_global_variable(&rbffi_StructInlineArrayClass);
713
857
 
858
+ rbffi_StructLayoutCharArrayClass = rb_define_class_under(rbffi_StructLayoutClass,
859
+ "CharArray", rbffi_StructInlineArrayClass);
860
+ rb_global_variable(&rbffi_StructLayoutCharArrayClass);
714
861
 
715
862
 
716
863
  rb_define_alloc_func(StructClass, struct_allocate);
@@ -756,10 +903,11 @@ rbffi_Struct_Init(VALUE moduleFFI)
756
903
  rb_define_method(rbffi_StructInlineArrayClass, "each", inline_array_each, 0);
757
904
  rb_define_method(rbffi_StructInlineArrayClass, "size", inline_array_size, 0);
758
905
  rb_define_method(rbffi_StructInlineArrayClass, "to_a", inline_array_to_a, 0);
759
- rb_define_method(rbffi_StructInlineArrayClass, "to_s", inline_array_to_s, 0);
760
- rb_define_alias(rbffi_StructInlineArrayClass, "to_str", "to_s");
761
906
  rb_define_method(rbffi_StructInlineArrayClass, "to_ptr", inline_array_to_ptr, 0);
762
907
 
908
+ rb_define_method(rbffi_StructLayoutCharArrayClass, "to_s", inline_array_to_s, 0);
909
+ rb_define_alias(rbffi_StructLayoutCharArrayClass, "to_str", "to_s");
910
+
763
911
  id_pointer_ivar = rb_intern("@pointer");
764
912
  id_layout_ivar = rb_intern("@layout");
765
913
  id_layout = rb_intern("layout");