ruby / ruby/fiddle

How to pass struct as argument of function

Open
#114 6 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
195
Forks
53
Avg merge
23h 57m
Merged PRs (30d)
1

Description

Hi, sorry for my english. I will show the problem with examples:

header.h
typedef struct {
    const char* content;
    uint32_t len;
} tc_string_data_t;

typedef struct tc_string_handle_t tc_string_handle_t;



tc_string_handle_t* tc_create_context(tc_string_data_t config);

tc_string_data_t tc_read_string(const tc_string_handle_t* handle);

void tc_destroy_string(const tc_string_handle_t* handle);

How its work in ruby with gem ffi

require "json"
require "ffi"


module Binding
    class TcStringDataT < FFI::Struct
      layout :content, :pointer,
        :len, :uint32
    end
end


module Binding
    extend FFI::Library
    ffi_lib "/path_to_lib"
    
    def self.setup_bindings
      attach_function :tc_create_context, [TcStringDataT.by_value], :pointer

      attach_function :tc_read_string, [:pointer], TcStringDataT.by_value

      attach_function :tc_destroy_string, [:pointer], :void
    end
end

config_json = {network: {endpoints: ["http://some_url"]}}.to_json

# make struct
data_struct = Binding::TcStringDataT.new
data_struct[:content] = FFI::MemoryPointer.from_string(config_json)
data_struct[:len] = config_json.bytesize

# create context
string_ref = Binding.tc_create_context(data_struct)

# read context response
result_data_struct = Binding.tc_read_string(string_ref)
result_string = result_data_struct[:content].read_string(result_data_struct[:len])

# destroy ref
Binding.tc_destroy_string(string_ref)

ffi gem works, but sometimes i get segmentation fault :(

So I decided to try to do it with fiddle !

But how ? How to do it with fiddle ? I climbed the entire Internet. I haven't found a single example of how to pass a struct to a function. There are only very few examples of how to pass ordinary primitives and not a single example of how to pass a structure. I have tried many options and still have not been able to achieve a result. Please help me !!! Write an example of calling these functions and passing arguments to them. Really looking forward to the answer.

Here is what I do with fidl:

require 'fiddle'
require 'fiddle/import'
require 'json'


module TestFiddle
  extend Fiddle::Importer
  extend Fiddle::CParser
  dlload('/lib_client.dylib')

  TcStringDataT = struct [
    'const char* content',
    'uint len'
  ]

  # tc_string_handle_t* tc_create_context(tc_string_data_t config);
  # extern 'TcStringDataT* tc_create_context(TcStringDataT config)' ## unknown type TcStringDataT
  extern 'TcStringDataT* tc_create_context(TcStringDataT* config)' ## OK

  # tc_string_data_t tc_read_string(const tc_string_handle_t* handle);
  # extern 'TcStringDataT tc_read_string(const TcStringDataT* handle)' ## unknown type TcStringDataT
  extern 'TcStringDataT* tc_read_string(const TcStringDataT* handle)' ## OK

  # void tc_destroy_string(const tc_string_handle_t* handle)
  # extern 'void tc_destroy_string(const TcStringDataT handle)' ## unknown type TcStringDataT
  extern 'void tc_destroy_string(const TcStringDataT* handle)' ## OK
end

config_json = {network: {endpoints: ["http://some_url"]}}.to_json

struct = TestFiddle::TcStringDataT.malloc
struct.content = Fiddle::Pointer.to_ptr(config_json)
struct.len = config_json.bytesize

# How to pass this struct ???
ctx_ptr = TestFiddle.tc_create_context(struct)  ## ERROR ERROR ERROR, many many zeros and ones

string_ptr = TestFiddle.tc_read_string(ctx_ptr)
struct = Test::TcStringDataT.new(string_ptr)
p struct.content.to_s

please help me with this 🙏

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Fiddle::Importer, Fiddle::CParser, and struct declarations shown in the issue, then reproduce the tc_create_context, tc_read_string, and tc_destroy_string calls against the supplied C header. Confirm how the struct argument and return value should be represented, and document a working example that avoids the reported errors and segmentation faults.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, ruby
Domain
tooling
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.