返回Ruby';来自C函数的指针

返回Ruby';来自C函数的指针,ruby,rubygems,ffi,fiddle,Ruby,Rubygems,Ffi,Fiddle,我目前正在开发一个高性能的Vector/Matrix Ruby gem C扩展,因为我发现内置的实现很麻烦,对于我个人遇到的大多数情况都不理想,而且在其他方面也不理想 我的第一种方法是在Ruby中实现为Fiddle::CStructEntity的一个子类,目标是使它们在不需要转换(例如传递到本机OpenGL函数)的情况下进行互操作优化。用C实现对数学有很大的好处,但我在尝试实现一个小函数时遇到了障碍 我希望有一个方法将Fiddle::Pointer返回到结构(基本上是一个指向Rdata->dat

我目前正在开发一个高性能的Vector/Matrix Ruby gem C扩展,因为我发现内置的实现很麻烦,对于我个人遇到的大多数情况都不理想,而且在其他方面也不理想

我的第一种方法是在Ruby中实现为
Fiddle::CStructEntity
的一个子类,目标是使它们在不需要转换(例如传递到本机OpenGL函数)的情况下进行互操作优化。用C实现对数学有很大的好处,但我在尝试实现一个小函数时遇到了障碍

我希望有一个方法将
Fiddle::Pointer
返回到结构(基本上是一个指向
Rdata->data
的指针。我希望返回一个实际的
Fiddle::pointer
对象。返回一个整数地址、压缩字符串等非常简单,使用它可以很容易地在Ruby方法中扩展以转换为
Fiddle::pointer

def ptr
  # Assume address is an integer address returned from C
  Fiddle::Pointer.new(self.address, self.size)
end
这就向我提出了一个问题,甚至可以从C中这样做吗?Fiddle不是核心库的一部分,它是标准库的一部分,因此,它实际上只是一个扩展本身


这个问题很简单,可以通过上面演示的几行Ruby代码轻松解决,但更奇怪的是,如果从C扩展返回
Fiddle
对象而不需要黑客的话,是否还可以呢?我找不到任何这样做的例子,而且当涉及到Fiddle的文档时,总是这样这个问题的解决方案其实相当简单,尽管不象我希望发现的那样优雅或干净

可能有更详细的方法来实现这一点,包括
Fiddle
的标题,并以此为基础进行构建,但这并不是一个真正可行的解决方案,因为我不想限制我的C扩展只与Ruby 2.0+一起工作,如果Ruby版本低于2.0

首先我包括
version.h
,它允许访问定义宏
RUBY\u API\u version\u MAJOR
,这是我真正需要知道的关于
Fiddle
是否会出现的所有信息

这将是一个简化版本,简单地展示如何将
Fiddle::Pointer
类作为
,以及如何创建实例

#if RUBY_API_VERSION_MAJOR >= 2

    rb_require("fiddle");
    VALUE fiddle = rb_const_get(rb_cObject, rb_intern("Fiddle"));
    rb_cFiddlePointer = rb_const_get(fiddle, rb_intern("Pointer"));

#endif
在本例中,该类存储在
rb_cFiddlePointer
中,然后可以使用它从C创建并返回
Fiddle::Pointer
对象

    // Get basic data about the struct
    struct RData *rdata = RDATA(self);
    VALUE *args = xmalloc(sizeof(VALUE) * 2);
    // Set the platform pointer-size address (could just use size_t here...)
    #if SIZEOF_INTPTR_T == 4
        args[0] = LONG2NUM((long) rdata->data);
    #elif SIZEOF_INTPTR_T == 8
        args[0] = LL2NUM((long long) rdata->data);
    #else 
        args[0] = INT2NUM(0);
    #endif
    // Get size of structure
    args[1] = INT2NUM(SIZE_OF_YOUR_STRUCTURE);
    VALUE ptr = rb_class_new_instance(2, args, rb_cFiddlePointer);
    xfree(args);
    return ptr;
将函数链接到实际的Ruby方法后,可以调用它以获得指向内存中内部结构的大小指针