0

I am currently working on a C string metric library and am writing bindings for ruby. Using ffi how can I attach a function with a signature like char *function(const char *, const char *)? The function in question will allocate a string on the heap with malloc and then return a pointer to that string.

I believe I will need to wrap the ffi-attached function in a ruby method so that I can convert the returned string pointer to a ruby string and release the old pointer.

mc110
  • 2,825
  • 5
  • 20
  • 21
Rostepher
  • 201
  • 2
  • 8

1 Answers1

0

After a bit of work and messing around in irb, I figured out how to safely wrap a C function that returns a char *. First it is necessary to wrap libc's free function.

module LibC
    extend FFI::Library

    ffi_lib FFI::Library::LIBC

    # attatch free
    attach_function :free, [:pointer], :void
end

Now that we have access to free, we can attach the function and wrap it in a ruby module function. I also included a helper method to check for valid string parameters.

module MyModule
    class << self
        extend FFI::Library

        # use ffi_lib to include the library you are binding

        def function(str)
            is_string(str)
            ptr = ffi_function(str)
            result = String.new(ptr.read_string)
            LibC.free(ptr)

            result
        end

        private

        # attach function and alias it as ffi_function
        attach_function :ffi_function, :function, [:string], :pointer

        # helper to verify strings
        def is_string(object)
            unless object.kind_of? String
                raise TypeError,
                    "Wrong argument type #{object.class} (expected String)"
            end
        end
    end
end

That's it, hope it helps anyone else who has a similar problem.

Rostepher
  • 201
  • 2
  • 8