如何在Ruby代码中调用C的fread()函数?

时间:2013-06-10 15:35:08

标签: ruby callback fread ffi

我有一个C代码,我需要转换为Ruby代码。 这是C代码供您参考。

    //bundle_ingest.h
    typedef void
    (* bundle_read_fn)(
        gsdk_void_t*    callback_data,
        gsdk_byte_t*    buffer,
        gsdk_size_t     buffer_size,
        gsdk_size_t*    p_bytes_read,
        gsdk_bool_t*    abort
        );

    gsdk_error_t bundle_ingest(
        gsdk_void_t*            callback_data,
        bundle_read_fn          bundle_read_fn
        );

    //main.c
    void bundle_read_callback(
        gsdk_void_t*    callback_data,
        gsdk_byte_t*    buffer,
        gsdk_size_t buffer_size,
        gsdk_size_t*    p_bytes_read,
        gsdk_bool_t*    abort
        )
    {
        if((callback_data == NULL) || (buffer == NULL) || (p_bytes_read == NULL))
        {
            *abort = TRUE;
            return;
        }

        *p_bytes_read = fread(buffer, 1, buffer_size, (FILE *)callback_data);
    }

    int main()
    {
        FILE             *fp = NULL;
        gsdk_error_t     error = GSDK_SUCCESS;

        fp = fopen("mybundle.b", "rb");

        //1. this call invokes the bundle_read_callback function
        //2. definition of bundle_ingest() is in bundle_ingest.dll which I am linking
        //
        error = bundle_ingest((void *)fp, bundle_read_callback); 

        //if error = 0, I get the desired file generated in my current working folder.
        return 0;   
    }

我的问题:我想在Ruby中实现相同的部分代码。 除了回调函数中的'fread'调用之外,我已经在Ruby中编写了所有代码。 任何人都可以向我提供在Ruby中对C的fread()函数的替代调用的方向或解决方案。仅供参考,我已经尝试了'ffi-libc',但这对我不起作用。

注意:我使用FFI在Ruby中调用C函数。 这是Ruby代码供您参考。

    module Bundle

            FFI.add_typedef(:pointer, :GsdkCallbacksS)

            callback :bundle_read_fn, [ :pointer, :pointer, :gsdk_size_t, :pointer, :pointer ], :void

            class GsdkCallbacksS < FFI::Struct
              layout(
                      :callback_fpbundle_read, :bundle_read_fn
                    )
            end

            attach_function :bundle_ingest, [ :pointer, :bundle_read_fn ], :gsdk_error_t
    end

    class Ingestion

        include Bundle

        BundleReadCallback = Proc.new do | callback_data, buffer, buffer_size, p_bytes_read, abort|

        puts "\ninside BundleReadCallback\n\n"

        if((callback_data == nil) or (buffer == nil) || (p_bytes_read == nil))
            abort.wtire_pointer(true)
          return
        end
        ##################################################################################
        ## TODO: Ruby alternate to C's fread()                                          ##
        ## C call: *p_bytes_read = fread(buffer, 1, buffer_size, (FILE *)callback_data);##
        ##################################################################################
        end 

        def ingest_bundle (bundlle_file)

         callback = GsdkCallbacksS.new
         callback[:callback_fpbundle_read] = BundleReadCallback

         size = File.size(bundle_file)
           open(bundle_file, "rb") do |io|
            fp = io.read(size)
            error = bundle_ingest(fp, callback[:callback_fpbundle_read])
            puts "bundle_ingest, error = #{error}"
            io.close
          end
        end
    end

    ### Ruby main.rb

    bi = Ingestion.new

    bi.ingest_bundle("mybundle.b")

1 个答案:

答案 0 :(得分:2)

Ruby中fread(3)的等价物是IO#read.

顺便说一下,R​​uby中的read(2)相当于IO#sysread.