Skip to content

@elabs-dev /byte_string.rb secret
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Some examples custom types for use in FFI libraries
# From: https://github.com/Burgestrand/spotify/blob/master/lib/spotify/types/byte_string.rb
module Spotify
module ByteString
extend FFI::DataConverter
native_type FFI::Type::POINTER
class << self
# Given either a String or nil, make an actual FFI::Pointer
# of that value, without an ending NULL-byte.
#
# @param [#to_str, nil] value
# @param ctx
# @return [FFI::Pointer]
def to_native(value, ctx)
value && begin
value = value.to_str
pointer = FFI::MemoryPointer.new(:char, value.bytesize)
pointer.write_string(value)
end
end
# no from_native, as we must return a pointer because we simply
# don’t know the length of a ByteString just by looking at the pointer.
def reference_required?
true
end
end
end
end
# From: https://github.com/Burgestrand/spotify/blob/master/lib/spotify/types/image_id.rb
module Spotify
# A custom data type for Spotify image IDs.
#
# It will convert strings to image ID pointers when handling
# values from Ruby to C, and it will convert pointers to Ruby
# strings when handling values from C to Ruby.
#
# Spotify image IDs are pointers to an array of 20 bytes, but
# in Ruby we treat them as strings.
module ImageID
extend FFI::DataConverter
native_type FFI::Type::POINTER
class << self
# @return [Integer] bytesize of image ID pointers.
def size
20
end
# Given a string, convert it to an image ID pointer.
#
# @param [#to_str, nil] value image id as a string
# @param ctx
# @return [FFI::Pointer] pointer to the image ID
def to_native(value, ctx)
value && begin
value = value.to_str
if value.bytesize != size
raise ArgumentError, "image id bytesize must be #{size}, was #{value.bytesize}"
end
pointer = FFI::MemoryPointer.new(:char, size)
pointer.write_string(value)
end
end
# Given a pointer, read a {.size}-byte image ID from it.
#
# @param [FFI::Pointer] value
# @param ctx
# @return [String, nil] the image ID as a string, or nil
def from_native(value, ctx)
value.read_string(size) unless value.null?
end
# FFI needs this to know if a reference to the native object
# should be kept. Since we allocate memory using MemoryPointer,
# we want the refernce to be kept.
#
# This is used if you assign the object to a struct, for exmaple.
def reference_required?
true
end
end
end
end
# From: https://github.com/Burgestrand/plaything/blob/master/lib/plaything/support/type_class.rb
class Plaything
module OpenAL
# TypeClass will return an FFI::DataConverter for a built-in FFI
# type. Since you can’t subclass FFI::Type::INT, for example, this
# method will return a class for a given type that you *can* subclass.
#
# Example usage:
#
# class Source < TypeClass(FFI::Type::INT)
# end
def self.TypeClass(type)
Class.new do
extend FFI::DataConverter
define_singleton_method(:type) do
type
end
class << self
def inherited(other)
other.native_type(type)
end
def to_native(source, ctx)
source.value
end
def from_native(value, ctx)
new(value)
end
def size
type.size
end
end
def initialize(value)
@value = value
end
def ==(other)
other.is_a?(self.class) and other.value == value
end
attr_reader :value
end
end
end
end
@Burgestrand

To any elabsians wondering why this is here, I created it for the upcoming blog post on FFI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.