carray-jit 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,17 @@
1
1
  require "digest"
2
- require "fiddle"
3
- require "fiddle/import"
2
+ require "carray/jit/native"
4
3
 
5
4
  class CArray
6
5
  module JIT
7
6
 
8
7
  # One parameter or return type, as the prototype spelled it.
9
8
  #
10
- # Fiddle's parser answers what the ABI needs and no more: every pointer
11
- # comes back as `TYPE_VOIDP`, so `const double *`, `double *` and `void *`
12
- # are one thing to it. That is enough to *call* a function and not enough
13
- # to *write* one, which is why the declarator's own text is kept beside
14
- # the code Fiddle assigned it.
15
- CType = Struct.new(:text, :fiddle, :computation, :pointer, :array,
9
+ # The type a call is made with answers what the ABI needs and no more:
10
+ # every pointer is `:pointer`, so `const double *`, `double *` and
11
+ # `void *` are one thing to it. That is enough to *call* a function and
12
+ # not enough to *write* one, which is why the declarator's own text is
13
+ # kept beside the name in Native::TYPES it was given.
14
+ CType = Struct.new(:text, :abi, :computation, :pointer, :array,
16
15
  :element, :const) do
17
16
  # True for a type that may be written into a signature but holds no
18
17
  # value a kernel or a body can compute with.
@@ -26,16 +25,16 @@ class CArray
26
25
  pointer && !element.nil?
27
26
  end
28
27
 
29
- # A C99 complex passed or returned by value. Fiddle cannot carry one,
30
- # so a call from Ruby goes through a shim; a call from a kernel is C
28
+ # A C99 complex passed or returned by value. A call from Ruby cannot
29
+ # carry one, so it goes through a shim; a call from a kernel is C
31
30
  # calling C and needs nothing.
32
31
  def complex?
33
- !pointer && CDeclaration::COMPLEX_CODES.value?(fiddle)
32
+ !pointer && CDeclaration::COMPLEX_CODES.value?(abi)
34
33
  end
35
34
 
36
35
  # `CMPLX` for a double complex, `CMPLXF` for a float one.
37
36
  def complex_build
38
- fiddle == :float_complex ? "CMPLXF" : "CMPLX"
37
+ abi == :float_complex ? "CMPLXF" : "CMPLX"
39
38
  end
40
39
 
41
40
  # C's own declarator puts an array's length where a reader can see it,
@@ -55,6 +54,13 @@ class CArray
55
54
  "#{text.sub(/\s*\[.*\]\z/, "")} #{name}[#{array if sized?}]"
56
55
  end
57
56
 
57
+ # The pointer an array argument decays to, as C spells it:
58
+ # `const double coef[3]` takes a `const double *`.
59
+ def decayed
60
+ return text unless array
61
+ "#{text.sub(/\s*\[.*\]\z/, "")} *"
62
+ end
63
+
58
64
  # @return [String] the type, as C spells it.
59
65
  def to_s
60
66
  text
@@ -63,12 +69,12 @@ class CArray
63
69
 
64
70
  # A C function a kernel body can call, and that C can be handed back.
65
71
  #
66
- # The binding is borrowed from Fiddle -- `Fiddle::Handle` finds the
67
- # library and the symbol, and `Fiddle::CParser` decides the ABI code of a
68
- # type, which is the same path `Fiddle::Importer#extern` takes. The
69
- # *call* is not borrowed: reaching a function through `Fiddle::Function`
70
- # costs a few hundred nanoseconds per cell, against single digits from
71
- # compiled C. Fiddle is asked where the function is; the kernel calls it.
72
+ # The binding is borrowed from Native -- it finds the library and the
73
+ # symbol, and decides what type a C spelling is on this machine. The
74
+ # *call* is not borrowed: reaching a function through a function Native
75
+ # makes costs a few hundred nanoseconds per cell, against single digits
76
+ # from compiled C. Native is asked where the function is; the kernel
77
+ # calls it.
72
78
  #
73
79
  # The address travels to the kernel in a buffer, the way a captured scalar
74
80
  # already does, rather than being linked against. That means no `-l`
@@ -259,9 +265,10 @@ class CArray
259
265
  @parameters.size
260
266
  end
261
267
 
262
- # The Fiddle types, for calling it from Ruby.
268
+ # The type codes of the layer Native stands for, for calling it from
269
+ # Ruby through that layer directly.
263
270
  def argument_types
264
- @parameters.map(&:fiddle)
271
+ @parameters.map { |type| Native::TYPES.fetch(type.abi, type.abi) }
265
272
  end
266
273
 
267
274
  # The C spelling of the pointer type, for the typedef a kernel emits.
@@ -305,13 +312,13 @@ class CArray
305
312
  return call_through_shim(arguments) if @shim
306
313
  if carries_a_complex?
307
314
  raise Unsupported,
308
- "`#{self}` carries a C99 complex by value, which Fiddle has " \
309
- "no type for, so it cannot be called from Ruby; a kernel " \
310
- "calls it as C calls it"
315
+ "`#{self}` carries a C99 complex by value, which a call " \
316
+ "from Ruby has no type for, so it cannot be called from " \
317
+ "here; a kernel calls it as C calls it"
311
318
  end
312
- @function ||= Fiddle::Function.new(@pointer, argument_types,
313
- @return_type.fiddle,
314
- name: label.to_s)
319
+ @function ||= Native.function(@pointer, @parameters.map(&:abi),
320
+ @return_type.abi, release_gvl: true,
321
+ name: label.to_s)
315
322
  arrays = []
316
323
  prepared = arguments.zip(@parameters).map { |argument, type|
317
324
  next argument unless type.indexable? && argument.is_a?(CArray)
@@ -334,7 +341,7 @@ class CArray
334
341
  slot = -1
335
342
  prepared = prepared.map { |value|
336
343
  next value unless arrays.any? { |_, buffer, _| buffer.equal?(value) }
337
- Fiddle::Pointer.new(bases[slot += 1][:pointer])
344
+ bases[slot += 1][:pointer]
338
345
  }
339
346
  @result = @function.call(*prepared)
340
347
  end
@@ -359,10 +366,10 @@ class CArray
359
366
  @return_type.complex? || @parameters.any?(&:complex?)
360
367
  end
361
368
 
362
- # Fiddle carries no complex, so the shim takes each complex argument as
363
- # a pair of doubles and writes a complex result back the same way.
364
- # Everything else keeps the type the declaration gave it and goes
365
- # through Fiddle as before -- including a pointer parameter, which is
369
+ # A call from Ruby carries no complex, so the shim takes each complex
370
+ # argument as a pair of doubles and writes a complex result back the
371
+ # same way. Everything else keeps the type the declaration gave it and
372
+ # is called as before -- including a pointer parameter, which is
366
373
  # still a CArray on this side.
367
374
  #
368
375
  # It is the same compiled body either way: the shim calls the function,
@@ -370,13 +377,13 @@ class CArray
370
377
  def call_through_shim (arguments)
371
378
  returns_complex = @return_type.complex?
372
379
  types = @parameters.map { |type|
373
- type.complex? ? Fiddle::TYPE_VOIDP : type.fiddle
380
+ type.complex? ? :pointer : type.abi
374
381
  }
375
- types << Fiddle::TYPE_VOIDP if returns_complex
382
+ types << :pointer if returns_complex
376
383
  @shim_function ||=
377
- Fiddle::Function.new(@shim, types,
378
- returns_complex ? Fiddle::TYPE_VOID
379
- : @return_type.fiddle)
384
+ Native.function(@shim, types,
385
+ returns_complex ? :void : @return_type.abi,
386
+ release_gvl: true)
380
387
  result = returns_complex ? String.new("\0" * 16) : nil
381
388
  arrays = []
382
389
  prepared = arguments.zip(@parameters).map { |argument, type|
@@ -396,7 +403,7 @@ class CArray
396
403
  slot = -1
397
404
  passed = prepared.map { |value|
398
405
  next value unless arrays.any? { |_, buffer, _| buffer.equal?(value) }
399
- Fiddle::Pointer.new(bases[slot += 1][:pointer])
406
+ bases[slot += 1][:pointer]
400
407
  }
401
408
  passed << result if returns_complex
402
409
  @result = @shim_function.call(*passed)
@@ -522,8 +529,8 @@ class CArray
522
529
  # f.on_error(nlopt["nlopt_force_stop"], opt)
523
530
  # f.watching { nlopt_optimize.call(opt, x, minf) }
524
531
  #
525
- # `hook` is the address of a `void (*)(void *)` -- a Fiddle::Pointer,
526
- # an Integer, or anything answering #to_i -- and `data` is the one
532
+ # `hook` is the address of a `void (*)(void *)` -- an Integer, or
533
+ # anything answering #to_i, as a pointer object does -- and `data` is the one
527
534
  # argument it is called with. It is called once, from the call whose
528
535
  # body put the flag up, and not again until the flag has been put down
529
536
  # and has gone up again; nothing about it reaches Ruby, so it may be
@@ -545,18 +552,17 @@ class CArray
545
552
  state = error_state
546
553
  return self unless state
547
554
  address = hook.nil? ? 0 : hook.to_i
548
- state.data[0, Fiddle::SIZEOF_VOIDP] =
549
- [data.nil? ? 0 : data.to_i].pack("J")
550
- state.hook[0, Fiddle::SIZEOF_VOIDP] = [address].pack("J")
555
+ Native.write(state.data, [data.nil? ? 0 : data.to_i].pack("J"))
556
+ Native.write(state.hook, [address].pack("J"))
551
557
  state.held = hook.nil? ? nil : [hook, data]
552
558
  self
553
559
  end
554
560
 
555
561
  private
556
562
 
557
- # One thread's copy of the four the compiled object carries -- the
558
- # flag, the hook's address, the pointer it is handed, and what a failed
559
- # call answers C with -- with the Ruby objects `#on_error` was given
563
+ # Where one thread's copy of the four the compiled object carries
564
+ # stands -- the flag, the hook's address, the pointer it is handed, and
565
+ # what a failed call answers C with -- with the Ruby objects `#on_error` was given
560
566
  # held beside them, so that nothing the C may still call is collected.
561
567
  ErrorState = Struct.new(:flag, :hook, :data, :standin, :held)
562
568
  private_constant :ErrorState
@@ -586,25 +592,21 @@ class CArray
586
592
  end
587
593
 
588
594
  def resolve_error_state
589
- out = String.new("\0" * (4 * Fiddle::SIZEOF_VOIDP))
595
+ out = String.new("\0" * (4 * Native::POINTER_SIZE))
590
596
  @error_state.call(out)
591
597
  flag, hook, data, standin = out.unpack("J4")
592
- ErrorState.new(Fiddle::Pointer.new(flag, 4),
593
- Fiddle::Pointer.new(hook, Fiddle::SIZEOF_VOIDP),
594
- Fiddle::Pointer.new(data, Fiddle::SIZEOF_VOIDP),
595
- Fiddle::Pointer.new(standin, 8),
596
- nil)
598
+ ErrorState.new(flag, hook, data, standin, nil)
597
599
  end
598
600
 
599
601
  # 0 where the body cannot fail at all.
600
602
  def error_code
601
603
  state = error_state
602
- state ? state.flag[0, 4].unpack1("l") : 0
604
+ state ? Native.read(state.flag, 4).unpack1("l") : 0
603
605
  end
604
606
 
605
607
  def write_error (code)
606
608
  state = error_state
607
- state.flag[0, 4] = [code].pack("l") if state
609
+ Native.write(state.flag, [code].pack("l")) if state
608
610
  end
609
611
 
610
612
  # The hook's address, cleared for the length of one call from Ruby,
@@ -612,14 +614,14 @@ class CArray
612
614
  def disarm_hook
613
615
  state = error_state
614
616
  return nil unless state
615
- held = state.hook[0, Fiddle::SIZEOF_VOIDP]
616
- state.hook[0, Fiddle::SIZEOF_VOIDP] = "\0" * Fiddle::SIZEOF_VOIDP
617
+ held = Native.read(state.hook, Native::POINTER_SIZE)
618
+ Native.write(state.hook, "\0" * Native::POINTER_SIZE)
617
619
  held
618
620
  end
619
621
 
620
622
  def rearm_hook (held)
621
623
  state = error_state
622
- state.hook[0, Fiddle::SIZEOF_VOIDP] = held if state && held
624
+ Native.write(state.hook, held) if state && held
623
625
  end
624
626
 
625
627
  # What a window does at its two ends. `#watching` is these with a
@@ -655,8 +657,8 @@ class CArray
655
657
  def hold_hook (address, data)
656
658
  state = error_state
657
659
  return nil unless state
658
- held = [state.hook[0, Fiddle::SIZEOF_VOIDP],
659
- state.data[0, Fiddle::SIZEOF_VOIDP], state.held]
660
+ held = [Native.read(state.hook, Native::POINTER_SIZE),
661
+ Native.read(state.data, Native::POINTER_SIZE), state.held]
660
662
  on_error(address, data)
661
663
  held
662
664
  end
@@ -664,8 +666,8 @@ class CArray
664
666
  def restore_hook (held)
665
667
  state = error_state
666
668
  return unless state && held
667
- state.hook[0, Fiddle::SIZEOF_VOIDP] = held[0]
668
- state.data[0, Fiddle::SIZEOF_VOIDP] = held[1]
669
+ Native.write(state.hook, held[0])
670
+ Native.write(state.data, held[1])
669
671
  state.held = held[2]
670
672
  end
671
673
 
@@ -675,14 +677,14 @@ class CArray
675
677
  def hold_standin (value)
676
678
  state = error_state
677
679
  return nil unless state
678
- held = state.standin[0, 8]
679
- state.standin[0, 8] = [value].pack("q")
680
+ held = Native.read(state.standin, 8)
681
+ Native.write(state.standin, [value].pack("q"))
680
682
  held
681
683
  end
682
684
 
683
685
  def restore_standin (held)
684
686
  state = error_state
685
- state.standin[0, 8] = held if state && held
687
+ Native.write(state.standin, held) if state && held
686
688
  end
687
689
 
688
690
  def raise_for (code)
@@ -718,7 +720,7 @@ class CArray
718
720
  # rule is that an unsized pointer is the caller's responsibility, and
719
721
  # writing `coef[3]` is how the caller asks to be checked.
720
722
  def check_array (array, type)
721
- wanted = CDeclaration::DATA_TYPES.fetch(type.element.fiddle)
723
+ wanted = CDeclaration::DATA_TYPES.fetch(type.element.abi)
722
724
  unless array.data_type_name == wanted.to_s
723
725
  raise Unsupported,
724
726
  "`#{type.text}` takes a #{wanted} array, and this one is " \
@@ -766,19 +768,16 @@ class CArray
766
768
 
767
769
  # Reads the subset of C declarations a signature may be written in.
768
770
  #
769
- # Fiddle's parser is used for what it is good at -- deciding the ABI code
770
- # of a type -- and this decides what that parser throws away: whether a
771
+ # Native is asked what it is good at -- what type a spelling is on this
772
+ # machine -- and this decides what that answer throws away: whether a
771
773
  # parameter is a pointer, and what it was a pointer to. Between them a
772
774
  # prototype yields both what is needed to call a function and what is
773
775
  # needed to write one.
774
776
  # @private
775
777
  module CDeclaration
776
778
 
777
- PARSER = ::Object.new.extend(Fiddle::CParser)
778
- private_constant :PARSER
779
-
780
779
  # The words a type may be spelled with. `<stdint.h>`'s exact-width
781
- # names are here because Fiddle knows them; there is no `float64_t`
780
+ # names are here because C has them; there is no `float64_t`
782
781
  # because C has no such type -- its integer types have exact-width
783
782
  # aliases and its floating types are `float` and `double`.
784
783
  KEYWORDS = %w[
@@ -789,11 +788,10 @@ class CArray
789
788
  size_t ssize_t ptrdiff_t intptr_t uintptr_t
790
789
  ].freeze
791
790
 
792
- # Fiddle has no code for a C99 complex -- its parser does not know the
793
- # word and the ABI it answers for has nowhere to put one -- so these
794
- # stand where a Fiddle code stands elsewhere. Symbols rather than
795
- # numbers, so that one reaching Fiddle by mistake is a TypeError there
796
- # and not a silently wrong width.
791
+ # Native has no type for a C99 complex -- a call from Ruby has nowhere
792
+ # to put one -- so these stand where a name in Native::TYPES stands
793
+ # elsewhere, and one reaching Native by mistake is refused there rather
794
+ # than taken for a wrong width.
797
795
  COMPLEX_CODES = { "double" => :double_complex,
798
796
  "float" => :float_complex }.freeze
799
797
 
@@ -802,12 +800,13 @@ class CArray
802
800
  # about what it declared.
803
801
  COMPLEX_WORDS = %w[_Complex complex].freeze
804
802
 
805
- # Fiddle answers `long double` with the code for `long`, silently, so it
806
- # is refused by name rather than trusted.
803
+ # A call from Ruby has no `long double` to make, and the parser behind
804
+ # Native takes it for `long` without saying so, so it is refused by name
805
+ # rather than asked about.
807
806
  REFUSED = {
808
- "long double" => "`long double` is not a type this reads: Fiddle " \
809
- "reports it as `long`, which would be the wrong " \
810
- "width without saying so",
807
+ "long double" => "`long double` is not a type this reads: there is " \
808
+ "nothing here to call with one, and taking it for " \
809
+ "`long` would be the wrong width without saying so",
811
810
  "long double _Complex" =>
812
811
  "`long double _Complex` is not a type this reads: there is no " \
813
812
  "long double here to make one of",
@@ -815,58 +814,59 @@ class CArray
815
814
 
816
815
  # The words C builds its integer types from. They may come in any
817
816
  # order and `int` may be left out -- `unsigned`, `long unsigned int`
818
- # and `int unsigned` are all C -- while Fiddle reads only some of those
819
- # orders, fails on a bare `unsigned`, and reads `int unsigned` as a
820
- # signed int without saying so. So a spelling made only of these is
821
- # counted here and handed to Fiddle in the one order it reads.
817
+ # and `int unsigned` are all C -- while the parser behind Native reads
818
+ # only some of those orders, fails on a bare `unsigned`, and reads `int
819
+ # unsigned` as a signed int without saying so. So a spelling made only
820
+ # of these is counted here and handed to Native in the one order it
821
+ # reads.
822
822
  INTEGER_WORDS = %w[signed unsigned char short int long].freeze
823
823
 
824
- # The CArray data type a pointer parameter takes, by the code Fiddle
824
+ # The CArray data type a pointer parameter takes, by the type Native
825
825
  # gave its element. This is the table CGenerator::STORAGE_C_TYPES
826
826
  # already holds, read the other way round -- nothing new is decided
827
827
  # here about how a C type and a CArray type correspond.
828
828
  DATA_TYPES = {
829
- :double_complex => :cmplx128,
830
- :float_complex => :cmplx64,
831
- Fiddle::TYPE_DOUBLE => :float64,
832
- Fiddle::TYPE_FLOAT => :float32,
833
- Fiddle::TYPE_CHAR => :int8,
834
- Fiddle::TYPE_UCHAR => :uint8,
835
- Fiddle::TYPE_SHORT => :int16,
836
- Fiddle::TYPE_USHORT => :uint16,
837
- Fiddle::TYPE_INT => :int32,
838
- Fiddle::TYPE_UINT => :uint32,
839
- Fiddle::TYPE_LONG => :int64,
840
- Fiddle::TYPE_LONG_LONG => :int64,
841
- # `unsigned long` and `size_t` arrive as the same code, and
829
+ :double_complex => :cmplx128,
830
+ :float_complex => :cmplx64,
831
+ :double => :float64,
832
+ :float => :float32,
833
+ :char => :int8,
834
+ :uchar => :uint8,
835
+ :short => :int16,
836
+ :ushort => :uint16,
837
+ :int => :int32,
838
+ :uint => :uint32,
839
+ :long => :int64,
840
+ :long_long => :int64,
841
+ # `unsigned long` and `size_t` arrive as the same type, and
842
842
  # `uint64_t` as the other one.
843
- Fiddle::TYPE_ULONG => :uint64,
844
- Fiddle::TYPE_ULONG_LONG => :uint64,
843
+ :ulong => :uint64,
844
+ :ulong_long => :uint64,
845
845
  }.freeze
846
846
 
847
- # Codes Fiddle may return, mapped to what a kernel computes them in.
847
+ # Types Native may answer, mapped to what a kernel computes them in.
848
848
  # Absent means the type may be written down but holds no value a body
849
849
  # can compute with -- `void`, and a pointer to it.
850
850
  COMPUTATION = {
851
851
  # A `float _Complex` computes in double complex, as a `float`
852
852
  # computes in double: the declaration says what the signature is,
853
853
  # and the body works in what Ruby would have worked in.
854
- :double_complex => :complex,
855
- :float_complex => :complex,
856
- Fiddle::TYPE_DOUBLE => :double,
857
- Fiddle::TYPE_FLOAT => :double,
858
- Fiddle::TYPE_CHAR => :int64,
859
- Fiddle::TYPE_UCHAR => :int64,
860
- Fiddle::TYPE_SHORT => :int64,
861
- Fiddle::TYPE_USHORT => :int64,
862
- Fiddle::TYPE_INT => :int64,
863
- Fiddle::TYPE_UINT => :int64,
864
- Fiddle::TYPE_LONG => :int64,
865
- Fiddle::TYPE_LONG_LONG => :int64,
854
+ :double_complex => :complex,
855
+ :float_complex => :complex,
856
+ :double => :double,
857
+ :float => :double,
858
+ :char => :int64,
859
+ :uchar => :int64,
860
+ :short => :int64,
861
+ :ushort => :int64,
862
+ :int => :int64,
863
+ :uint => :int64,
864
+ :long => :int64,
865
+ :long_long => :int64,
866
866
  # uint64 is a computation type of its own, precisely because int64
867
867
  # cannot carry what it holds; CArray has the array to match.
868
- Fiddle::TYPE_ULONG => :uint64,
869
- Fiddle::TYPE_ULONG_LONG => :uint64,
868
+ :ulong => :uint64,
869
+ :ulong_long => :uint64,
870
870
  }.freeze
871
871
 
872
872
  module_function
@@ -992,14 +992,14 @@ class CArray
992
992
  code = if !pointer && (complex = complex_code(spelling))
993
993
  complex
994
994
  else
995
- fiddle_code(pointer ? "void *" : spelling, text, prototype)
995
+ abi_code(pointer ? "void *" : spelling, text, prototype)
996
996
  end
997
997
  # What it points at, for a pointer that points at numbers. `void *`
998
998
  # has no element, which is what keeps it a slot.
999
999
  element = nil
1000
1000
  if pointer && spelling != "void"
1001
1001
  element_code = complex_code(spelling) ||
1002
- fiddle_code(spelling, text, prototype)
1002
+ abi_code(spelling, text, prototype)
1003
1003
  if COMPUTATION[element_code]
1004
1004
  element = CType.new(spelling, element_code,
1005
1005
  COMPUTATION[element_code], false, nil, nil,
@@ -1011,7 +1011,7 @@ class CArray
1011
1011
  end
1012
1012
 
1013
1013
  # `long unsigned int` as `unsigned long`, `unsigned` as `unsigned int`:
1014
- # the order Fiddle reads, for a spelling made only of INTEGER_WORDS.
1014
+ # the order Native reads, for a spelling made only of INTEGER_WORDS.
1015
1015
  # Anything else is handed back untouched. A combination C does not
1016
1016
  # have -- `signed unsigned`, `short long`, three `long`s -- is refused
1017
1017
  # here rather than left to a parser that has been seen to guess.
@@ -1032,7 +1032,7 @@ class CArray
1032
1032
  sign = count.key?("unsigned") ? "unsigned " : ""
1033
1033
  width = base.first || { 0 => "int", 1 => "long", 2 => "long long" }.fetch(longs)
1034
1034
  # `signed char` is a type of its own in C, apart from plain `char`,
1035
- # and Fiddle reads both as the one byte they are.
1035
+ # and Native reads both as the one byte they are.
1036
1036
  sign = "signed " if width == "char" && count.key?("signed")
1037
1037
  "#{sign}#{width}"
1038
1038
  end
@@ -1046,11 +1046,11 @@ class CArray
1046
1046
  COMPLEX_CODES[(words - COMPLEX_WORDS).join(" ")]
1047
1047
  end
1048
1048
 
1049
- def fiddle_code (spelling, text, prototype)
1050
- PARSER.parse_ctype(spelling)
1051
- rescue StandardError
1049
+ def abi_code (spelling, text, prototype)
1050
+ type = Native.c_type(spelling)
1051
+ return type if type
1052
1052
  raise Unsupported,
1053
- "`#{text.strip}` in `#{prototype}` is not a type Fiddle knows. " \
1053
+ "`#{text.strip}` in `#{prototype}` is not a type this knows. " \
1054
1054
  "C's own spellings are what this takes, and `float64_t` is not " \
1055
1055
  "one of them -- C's integer types have exact-width names, its " \
1056
1056
  "floating types are `float` and `double`"
@@ -1069,7 +1069,7 @@ class CArray
1069
1069
  # or nothing at all, which searches what the process has already loaded.
1070
1070
  #
1071
1071
  # `extern` is C's own word for a body that lives elsewhere, and that is
1072
- # all this does: it asks Fiddle where the function is. Nothing is
1072
+ # all this does: it asks Native where the function is. Nothing is
1073
1073
  # compiled here, which is the difference from `jit_function` and the
1074
1074
  # reason the two are not one method with a branch in it.
1075
1075
  #
@@ -1312,8 +1312,8 @@ class CArray
1312
1312
  def bind_c_function (prototype, name, return_type, parameters, from)
1313
1313
  handle = library_handle(from)
1314
1314
  begin
1315
- pointer = handle[name.to_s]
1316
- rescue Fiddle::DLError => error
1315
+ pointer = Native.address(handle, name.to_s)
1316
+ rescue Native::LinkError => error
1317
1317
  raise Unsupported,
1318
1318
  "`#{name}` was not found in " \
1319
1319
  "#{from ? from.inspect : "the loaded libraries"} " \
@@ -1437,7 +1437,7 @@ class CArray
1437
1437
  # Every other return type with no computation behind it is a pointer,
1438
1438
  # which a body cannot produce: there is nothing here to take an
1439
1439
  # address of that would outlive the call.
1440
- returns_nothing = return_type.fiddle == Fiddle::TYPE_VOID &&
1440
+ returns_nothing = return_type.abi == :void &&
1441
1441
  !return_type.pointer
1442
1442
  unless return_type.computation || returns_nothing
1443
1443
  raise Unsupported,
@@ -1509,8 +1509,8 @@ class CArray
1509
1509
  c_source = generator.generate_function(
1510
1510
  symbol, names, parameters, return_type.text, return_type.computation)
1511
1511
  # A signature carrying a complex by value gets a second entry point
1512
- # for Ruby to reach it by, since Fiddle has no such type to call
1513
- # with. Only such a signature: everything else is called directly,
1512
+ # for Ruby to reach it by, since a call from Ruby has no such type
1513
+ # to call with. Only such a signature: everything else is called directly,
1514
1514
  # and pays nothing for a road it does not take.
1515
1515
  shim_symbol = nil
1516
1516
  if return_type.complex? || parameters.any?(&:complex?)
@@ -1530,9 +1530,9 @@ class CArray
1530
1530
  # that two objects generated this way can be linked side by side.
1531
1531
  error_state = if generator.uses_error_flag?
1532
1532
  accessor = CGenerator.error_state_name(symbol)
1533
- Fiddle::Function.new(handle[accessor],
1534
- [Fiddle::TYPE_VOIDP],
1535
- Fiddle::TYPE_VOID, name: accessor)
1533
+ Native.function(Native.address(handle, accessor),
1534
+ [:pointer], :void, release_gvl: true,
1535
+ name: accessor)
1536
1536
  end
1537
1537
  # A body that reports failures is generated a second time for pasting,
1538
1538
  # with the flag as a parameter. A second generator rather than the
@@ -1548,9 +1548,10 @@ class CArray
1548
1548
  return_type.computation,
1549
1549
  error_parameter: true)
1550
1550
  end
1551
- CFunction.new(name, prototype, return_type, parameters, handle[symbol],
1551
+ CFunction.new(name, prototype, return_type, parameters,
1552
+ Native.address(handle, symbol),
1552
1553
  symbol: symbol,
1553
- shim: shim_symbol && handle[shim_symbol],
1554
+ shim: shim_symbol && Native.address(handle, shim_symbol),
1554
1555
  block: block, c_source: generator.provenance + c_source,
1555
1556
  origin: origin, error_state: error_state,
1556
1557
  definition: pasted.function_definition,
@@ -1591,7 +1592,7 @@ class CArray
1591
1592
  end
1592
1593
  <<~C
1593
1594
 
1594
- /* Fiddle has no type for a C99 complex, so a call from Ruby comes
1595
+ /* A call from Ruby has no type for a C99 complex, so it comes
1595
1596
  through here: the complex arguments arrive as the two doubles
1596
1597
  one is laid out as, and a complex result goes back the same way.
1597
1598
  A kernel calls the function above directly, C to C. */
@@ -1659,12 +1660,12 @@ class CArray
1659
1660
 
1660
1661
  def library_handle (from)
1661
1662
  case from
1662
- when nil then Fiddle::Handle::DEFAULT
1663
- when Fiddle::Handle then from
1664
- when String then Fiddle::Handle.new(from)
1663
+ when nil then Native.loaded_libraries
1664
+ when Native::Library then from
1665
+ when String then Native.open_library(from, global: true)
1665
1666
  else
1666
1667
  raise Unsupported,
1667
- "`from:` takes a library name or a Fiddle::Handle, " \
1668
+ "`from:` takes a library name or a #{Native::Library}, " \
1668
1669
  "got #{from.class}"
1669
1670
  end
1670
1671
  end