How to pass struct as argument of function

オープン
#114 コメント 6 件 リアクション 1 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
25/100
issue の種類
ドキュメント
明瞭さ
説明が足りない
活発さ
停滞
技術スタック
c, ruby
領域
tooling

調査の方向性

Issue に示されている Fiddle::Importer、Fiddle::CParser、および struct の宣言から始め、提供された C ヘッダーに対して tc_create_context、tc_read_string、tc_destroy_string の呼び出しを再現します。struct 引数と戻り値をどのように表現すべきか確認し、報告されているエラーや segmentation fault を回避する動作する例を文書化します。

索引モデルが issue の本文から書いたものです。

説明

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 🙏

主要言語
Ruby
スター
195
フォーク
53
平均マージ
23時間 57分
マージ済み PR(30日)
1

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

ruby/fiddle のほかの issue

ruby/fiddle の issue をすべて見る

似ている issue

Ruby の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。