查看: 2570|回复: 2

[随意闲聊] 某搞笑而高效的优化方法..Ruby翻·译

[复制链接]
梦石
0
星屑
13562
在线时间
2753 小时
注册时间
2014-10-4
回帖
705

R考场第七期纪念奖

发表于 2018-2-19 22:44:11 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
简单说 就是把 ruby 代码翻译成 c 然后编译...乍看很诡异对吧
这个思路其实很早很早就有了,不过比较懒,一直拖着没什么实际行动 当然现在也不算有什么实质的行动..
操作起来还是蛮简单的
ruby 是拿 c 写的,ruby 原生的类/模块以及 RGSS 都是拿 c 写的然后编译的。游戏的本体代码也完全可以这样。(取关键部分翻译)
只需要反汇编取得关键函数的地址就能在此基础上进行翻译
翻译好再一番编译变 dll 然后进脚本去调用初始化一下就成了
搞笑就在于 直接写 c 作为拓展库也就算了 从 ruby 写回 c ?你在搞笑吗
高效在于省去了解释的过程 直接运行编译好的机器码 速度飞快
测试了一下效率起码是几倍 乃至十几倍 真的..
我就测试了一些 一个用 c 写 一个用 ruby 写 然后重复调用比较
方法越是复杂效率提升就越多
其余的没测试 因为 翻译还是 比较烦

高效一是在于编译好了
二是在于可以省略一些 ruby 的操作方式反之用 c 的方式取代
三是在于真·多线程

毕竟翻译不可能是一模一样来的

缺点一是烦
二是这种做法没啥必要 本来也够快了

单纯为了好玩吧

一直在用XP,XP的 ruby 版本是 1.8.1
下面一份是 RGSS103J 的大部分翻译所需的函数地址
一份是我翻译的这版本 ruby 源码的 README.EXT
翻译了绝大部分,其余对翻译没啥帮助 假如觉得我翻译的很怪请参考原文本
里面有基础知识啊操作全局实例变量常量啊定义函数类模块啊 c 和 ruby 之间的数据交流转换啊等等翻译所需要的东西
另外随时可以翻翻源码

[fold=函数地址]    后面的十六进制数值为相对 dll 基址的偏移
        即若基址为 0x10000000 那么第一个函数指针为 0x1007DF30
        rb_define_global_const    7DF30
    rb_define_private_method    209B0
        rb_global_variable        3D430
        rb_intern                   52F7B
        rb_define_alloc_func      26950
        rb_define_variable          7EC50
        rb_float_new              48F80
        rb_define_alias             20BD0
        rb_raise                  25610
        rb_iv_set                   7E070
        rb_iv_get                 7E050
        rb_uint2inum                1D520
        rb_num2ulong              4A3D0
        rb_int2inum                 1D540
        rb_to_id                  4CBD0
        rb_const_get                7E580
        rb_const_set              7DEB0
        rb_funcall                  363C0
        rb_float_new              48F80
        rb_ary_new2                 1A110
        rb_singleton_class        20A10
        rb_define_hooked_variable   7EC00
        rb_global_variable        3D430
        rb_define_global_function   20BB0
        rb_define_module          20400
        rb_define_module_function   20B80
        rb_define_class           20210
        rb_define_singleton_method  20B50
        rb_include_module         20610
        rb_define_method            20970
        rb_define_const           7DED0
        rb_str_new2                 72CD0
        rb_define_class_under     202D0
        rb_scan_args                20C00[/fold]
[fold=README.EXT.zh]这个文档解释了怎么写 Ruby 的拓展库。

1.基础知识

C语言中变量有类型而数据没有类型。相反,Ruby中变量没有类型而数据有,因而语言间的数据需要经过转换。

Ruby中的数据由C的类型 'VALUE' 表示。每个 VALUE 类型的数据有它自身的数据类型。

从一个 VLAUE 中获取 C 的数据,你需要:

(1) 确认此 VALUE 的数据类型
(2) 将此 VALUE 转换成 C 中的数据

数据类型的错误转换可能导致严重的问题。

1.1 数据类型

Ruby 解释器有以下几种数据类型:

        T_NIL                nil
        T_OBJECT        ordinary object
        T_CLASS                class
        T_MODULE        module
        T_FLOAT                floating point number
        T_STRING        string
        T_REGEXP        regular expression
        T_ARRAY                array
        T_FIXNUM        Fixnum(31bit integer)
        T_HASH                associative array
        T_STRUCT        (Ruby) structure
        T_BIGNUM        multi precision integer
        T_FILE                IO
        T_TRUE                true
        T_FALSE                false
        T_DATA                data
        T_SYMBOL    symbol

此外,内部还使用一些其他的数据类型:

        T_ICLASS
        T_MATCH
        T_UNDEF
        T_VARMAP
        T_SCOPE
        T_NODE

多数类型由 C 结构体表示。

1.2 检测 VALUE 的数据类型

ruby.h 中的宏 TYPE() 返回 VALUE 的数据类型。返回值为上文所述的常量 T_XXXX。为处理数据类型,你的代码大概长这样:

  switch (TYPE(obj)) {
    case T_FIXNUM:
      /* process Fixnum */
      break;
    case T_STRING:
      /* process String */
      break;
    case T_ARRAY:
      /* process Array */
      break;
    default:
      /* raise exception */
      rb_raise(rb_eTypeError, "not valid value");
      break;
  }

这是数据类型检查函数

  void Check_Type(VALUE value, int type)

若 VALUE 非指定类型则弹出异常。

更为便捷的检查 fixnum 和 nil 形的宏见下

  FIXNUM_P(obj)
  NIL_P(obj)

1.3 将 VALUE 转换成 C 数据

T_NIL, T_FALSE, T_TRUE 的数据类型分别为 nil, true, false。他们是数据类型中的单一构成类。

数据 T_FIXNUM 是一个 31 位长的fixnum(某些机器上为 63 位),能用宏 FIX2INT() 转换成 C 的整数。
NUM2INT()能把任何 Ruby 数字转换成 C 整数。宏 NUM2INT() 里有一个类型检查,因此转换失败会产生异常。
类似的,NUM2DBL() 用来获取一个双精度浮点数。

为从 VALUE 中获取 char*,版本 1.7 建议使用新宏 StringValue() 与 StringValuePtr()。
StringValue(var) 会将 var 的值转换成 "var.to_str()"。StringValuePtr(var)也转换 var的值并
返回 var 的 char*。若 var 为 String 这些宏会略过转换。注意宏的参数需为左值,因为它会被改变。

此处略去一部分 1.6 版本及之前的问题说明。

其他数据类型有对应的 C 结构体。例如,结构体 RArray 对应 T_ARRAY 等。有对应结构体的类型的 VALUE
能用来获取指向结构体的指针。所用到的宏对应不同类型有着 RXXXX 的形式。例如,RARRAY(obj)。详见 ruby.h

例如,`RSTRING(size)->len' 表示获取 Ruby 字符串对象的长度。所申请的内存区能用`RSTRING(str)->ptr'访问。
对于数组,用`RARRAY(ary)->len'和`RARRAY(ary)->ptr'。

注意:除非你对结果够自信,不要直接改变结构体的值。这会导致许多有趣的 bug。

1.4 将 C 类型转换成 VALUE

为将 C 数据转换为 Ruby 中的值:

  * FIXNUM

    左移一位,最低位置 1.

  * 其他指针值

    转换为 VALUE.

你能通过检查最低位判定一个 VALUE 是指针与否。

注意 Ruby 不允许随意的指针成为 VALUE。它们应该为 Ruby 已知结构体的指针。这些结构体定义于 ruby.h。

使用以下的宏将 C 中的数字转换为 Ruby 的值。

  INT2FIX()        用于31位以内的整数.
  INT2NUM()        用于任意大小的整数.

INT2NUM() 会把一个整数转换为 Bignum,如果它超出了 FIXNUM 的范围,不过稍微慢点。

1.5 操作 Ruby 中的数据

正如我上文所提,修改一个对象的内部结构不被建议。用 Ruby 解释器提供的函数。下列部分函数。

字符串函数

  rb_str_new(const char *ptr, long len)

    创造一个新的 Ruby 字符串。

  rb_str_new2(const char *ptr)

        由 C 的字符串创造一个 Ruby 字符串。这与 rb_str_new(ptr, strlen(ptr)) 等价。

  rb_tainted_str_new(const char *ptr, long len)

        创造一个新的污染的 Ruby 字符串。外部数据源获取的字符串应为污染的。

  rb_tainted_str_new2(const char *ptr)

    类同

  rb_str_cat(VALUE str, const char *ptr, long len)

        从 ptr 往 Ruby 字符串后添加 len 字节。

数组函数

  rb_ary_new()

    创建一个没有元素的数组

  rb_ary_new2(long len)

        创建一个没有元素的数组,同时申请内存以储存 len 个元素。

  rb_ary_new3(long n, ...)

        由参数创造一个 n 个元素的数组。

  rb_ary_new4(long n, VALUE *elts)

        由 C 数组创造一个 n 个元素的数组。

  rb_ary_push(VALUE ary, VALUE val)
  rb_ary_pop(VALUE ary)
  rb_ary_shift(VALUE ary)
  rb_ary_unshift(VALUE ary, VALUE val)

        数组操作。所有函数的第一个参数必须为数组, They may dump core if other types given.会挂 ?

2. 用 C 拓展 Ruby

2.1 为 Ruby 添加新功能

你可以为 Ruby 解释器添加新的功能如类,方法等。Ruby 提供定义以下事物的接口。

* Classes, Modules
* Methods, Singleton Methods
* Constants

2.1.1 类/模块 定义

用以下函数定义类或模块。

  VALUE rb_define_class(const char *name, VALUE super)
  VALUE rb_define_module(const char *name)

这些函数返回新创建的类或模块。建议保存它们以便之后使用。

用以下函数定义嵌套类或模块。

  VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
  VALUE rb_define_module_under(VALUE outer, const char *name)

2.1.2 方法/单体方法 定义

用以下函数定义方法或单体方法。

  void rb_define_method(VALUE klass, const char *name,
                        VALUE (*func)(), int argc)

  void rb_define_singleton_method(VALUE object, const char *name,
                                  VALUE (*func)(), int argc)

`argc'表示 C 函数需要的参数数,必须低于 17.但我相信你用不到那么多。:-)

若`argc'为负数,这指定了调用序列类型而非参数个数。

若 argc 为 -1,C 函数会按以下形式调用:

  VALUE func(int argc, VALUE *argv, VALUE obj)

argc 是实际参数数,argv 是参数的 C 数组,obj 是函数接收者。

若 argc 为 -2,参数通过 Ruby 数组传入。函数会按以下形式调用。

  VALUE func(VALUE obj, VALUE args)

obj 为函数接收者,argv 是包含实际参数的 Ruby 数组。

此外还有两个定义方法的函数。第一个是定义私有方法:

  void rb_define_private_method(VALUE klass, const char *name,
                                VALUE (*func)(), int argc)

另一个是定义模块函数,这等价于模块的私有与单体方法。例如,sqrt 是定义在 Math 的模块函数。它能以以下形式调用。

  Math.sqrt(4)

或

  include Math
  sqrt(4)

用以下函数定义模块函数:

  void rb_define_module_function(VALUE module, const char *name,
                                 VALUE (*func)(), int argc)

对了,此外,函数类方法,即定义在 Kernel 模块的私有方法,可通过以下形式定义:

  void rb_define_global_function(const char *name, VALUE (*func)(), int argc)

定义方法的别名:

  void rb_define_alias(VALUE module, const char* new, const char* old);

2.1.3 常量定义

有两个函数用以定义常数:

  void rb_define_const(VALUE klass, const char *name, VALUE val)
  void rb_define_global_const(const char *name, VALUE val)

前者用于定义指定类/模块下的常数。后者用于定义一个全局常数。

2.2 在 C 中使用 Ruby 的功能

有多种方式用 C 代码调用 Ruby 功能。

2.2.1 执行字符串中的 Ruby 程序

从 C 程序中调用 Ruby 功能最简单的方法就是 eval,下面这个函数就行。

  VALUE rb_eval_string(const char *str)

eval 执行于当前程序的域,因此最内部的方法的局部变量都能被访问到。

2.2.2 ID 或 Symbol

你也可以直接触发方法而不需借助字符串。首先我得解释一下 symbols (它的数据类型是 ID).
ID 是表示 Ruby 标识符如变量名的整数。它能以以下形式从 Ruby 访问。

:Identifier

你能用以下函数从一个字符串用 C 代码获取 symbol 值:

  rb_intern(const char *name)

2.2.3 从 C 中触发 Ruby 方法

你能用以下函数直接触发方法:

  VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)

这个函数在接收者对象上触发一个由 symbol mid 指定的方法

2.2.4 访问变量和常数

你能用访问函数访问类变量和实例变量。全局变量在 C 中和 Ruby 中共用。但是无法访问 Ruby 的局部变量。

以下方法用于访问/修改实例变量:

  VALUE rb_ivar_get(VALUE obj, ID id)
  VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)

id 必须为 symbol,可由 rb_intern() 获得。

获取类/模块的常量:

  VALUE rb_const_get(VALUE obj, ID id)

定义常量见 2.1.3

3. Ruby 和 C 的信息共享

3.1 C 中可访问的 Ruby 常量

以下 Ruby 常量可在 C 中引用。

  Qtrue
  Qfalse

布尔值。Qfalse 在 C 中也是 false。

  Qnil

C 下的 Ruby nil 值。

3.2 C 和 Ruby 共享的全局变量

信息于这两个环境可通过全局变量共享。用以下函数定义全局变量:

  void rb_define_variable(const char *name, VALUE *var)

此函数定义了两个环境共享的变量。在 C 中由 var 指向的变量在 Ruby 中通过变量名访问。

你可以用以下函数定义只读(对于 Ruby 来说)变量:

  void rb_define_readonly_variable(const char *name, VALUE *var)

你可以定义钩子变量。存取函数(getter and setter)在钩子变量被读/写时被调用。

  void rb_define_hooked_variable(constchar *name, VALUE *var,
                                 VALUE (*getter)(), void (*setter)())

假如你只需要用到 setter 或 getter 其一,将不需要的置 0.若两个钩子函数都是 0,那么定义的变量与一般变量一致。

  void rb_define_virtual_variable(const char *name,
                                  VALUE (*getter)(), void (*setter)())

这个函数定义没有对应 C 值的 Ruby 全局变量。其值只能通过钩子获取/改变。

getter 和 setter 函数的原型见下:

  (*getter)(ID id, void *data, struct global_entry* entry);
  (*setter)(VALUE val, ID id, void *data, struct global_entry* entry);

3.3 封装 C 数据为 Ruby 对象

用以下函数封装 C 指针为 Ruby 对象(即所谓的 DATA)

  Data_Wrap_Struct(klass, mark, free, ptr)

返回值是创造好的 DATA 对象。klass 参数是 DATA 对象的类。mark 参数是用来标记此数据指向的 Ruby 对象的函数。
free 参数是用来释放指针内申请了的内存的函数。若为 -1,指针会被单纯的释放。函数 mark 和 free 会在垃圾收集机制中被调用。

你可以很方便的申请内存并封装结构体。

  Data_Make_Struct(klass, type, mark, free, sval)

这个宏返回一个申请了内存的 Data 对象,即将指向结构体的指针封装。宏的运作过程如下:

  (sval = ALLOC(type), Data_Wrap_Struct(klass, mark, free, sval))

参数 klass,mark 和 free 和 Data_Wrap_Struct() 中的一样。sval 是指向申请了内存的结构体的指针,注意指针类型应与所需类型一致。

用以下宏从 Data 对象中取得 C 指针。

  Data_Get_Struct(obj, type, sval)

sval 会被赋值为指向结构体的指针。

细节见下面的例子。

4. 例子 - 创造 dbm 拓展

下面就是创造一个拓展库的例子。这是个用来访问 DBMs(数据库管理系统) 的拓展。完整的源码包含在源码目录 ext/ 下面。

(1) 新建目录

  % mkdir ext/dbm

在 ext 目录下新建拓展库的目录。

(2) 新建 MANIFEST 文件

  % cd ext/dbm
  % touch MANIFEST

拓展库目录下应该有这个文件。暂时新建一个空的就好。

(3) 设计库

在创造它之前,你需要想想这个库有什么功能。

(4) 敲代码

你得为你的拓展库写 C 代码。假如你的库只有一个源文件,其名建议为``库名.c''。假如有多个源文件,最好别这么取。
在有些平台上会和中间文件``库名.o''冲突。

Ruby 会执行名为``Init_LIBRARY''的初始化函数。例如,``Init_dbm()''会在库加载的时候被执行。

下面是一个初始化函数的例子。

--
Init_dbm()
{
    /* 定义 DBM 类 */
    cDBM = rb_define_class("DBM", rb_cObject);
    /* DBM 包含 Enumerate 模块 */
    rb_include_module(cDBM, rb_mEnumerable);

        /* DBM 有个类方法 open(): 参数以 C 数组形式传入 */
    rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);

    /* DBM 实例方法 close(): 无参 */
    rb_define_method(cDBM, "close", fdbm_close, 0);
    /* DBM 实例方法 []: 一个参数 */
    rb_define_method(cDBM, "[]", fdbm_fetch, 1);
                :

        /* 储存 DBM 实例变量用的 ID */
    id_dbm = rb_intern("dbm");
}
--

用 Data_Make_Struct 封装 dbm 结构体。

--
struct dbmdata {
    int  di_size;
    DBM *di_dbm;
};


obj = Data_Make_Struct(klass, struct dbmdata, 0, free_dbm, dbmp);
--

以上代码将 dbmdata 结构体封装为 Ruby 对象。避免直接封装 DBM*,因为我们要缓存对象的大小信息。

我们定义以下宏用来从 Ruby 对象取得 dbmdata 结构体。

--
#define GetDBM(obj, dbmp) {\
    Data_Get_Struct(obj, struct dbmdata, dbmp);\
    if (dbmp->di_dbm == 0) closed_dbm();\
}
--

这种复合的宏能取得结构体并作关闭检查。

有三种方式取得方法的参数。第一种,固定参数的方法像这样接收参数:

--
static VALUE
fdbm_delete(obj, keystr)
    VALUE obj, keystr;
{
        :
}
--

函数第一个参数是接收对象本身,剩余的是方法的参数。

第二种,不固定参数像这样接收:

--
static VALUE
fdbm_s_open(argc, argv, klass)
    int argc;
    VALUE *argv;
    VALUE klass;
{
        :
    if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
        mode = 0666;                /* default value */
    }
        :
}
--

第一个参数是传入参数的个数,第二个是参数构成的 C 数组,第三个参数是方法的接收对象。

你能用函数 rb_scan_args() 检查并获取参数。例如,"11" 表示这个方法需要至少一个参数和最多两个参数。

不固定参数的方法也能以 Ruby 数组的形式接收参数:

--
static VALUE
fdbm_indexes(obj, args)
    VALUE obj, args;
{
        :
}
--

第一个参数是接收对象,第二个参数是包含参数的 Ruby 数组。

** 注意

GC 应当知晓引用 Ruby 对象但是不对 Ruby 解释器开放的全局变量,用以下函数保护它们

  void rb_global_variable(VALUE *var)

(5) 准备 extconf.rb

若 extconf.rb 存在,其会被执行以生成 Makefile。否则编译机制会尝试生成 Makefile。

extconf.rb 用来检查编译环境等。你需要在文件头部写上

  require 'mkmf'

你可以用下面的函数来检查各种环境条件。

  have_library(lib, func): 检查包含函数的库是否存在
  have_func(func, header): 检查函数是否存在
  have_header(header): 检查头文件是否存在
  create_makefile(target): 生成 Makefile

下面变量的值会影响 Makefile
下面直到附录不翻了 没啥帮助
..
...
....

附录 A. Ruby 源文件总览

ruby 语言核心

  class.c
  error.c
  eval.c
  gc.c
  object.c
  parse.y
  variable.c

公用函数

  dln.c
  regex.c
  st.c
  util.c

ruby 解释器构架

  dmyext.c
  inits.c
  main.c
  ruby.c
  version.c

类库

  array.c
  bignum.c
  compar.c
  dir.c
  enum.c
  file.c
  hash.c
  io.c
  marshal.c
  math.c
  numeric.c
  pack.c
  prec.c
  process.c
  random.c
  range.c
  re.c
  signal.c
  sprintf.c
  string.c
  struct.c
  time.c

附录 B. Ruby 拓展 API 索引

** 类型

VALUE

Ruby 对象的类型。诸结构体如 RString 定义在 ruby.h。用宏如 RSTRING(obj) 来引用结构体中的值。

** 变量和常数

Qnil

常量: nil 对象

Qtrue

常量: true 对象(默认的真值)

Qfalse

常量: false 对象

** C 指针封装

Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval)

将一 C 指针封装为 Ruby 对象。若该对象引用了其他 Ruby 对象,在 GC 过程中它们应当被 mark 函数标记出来。不然置 mark 为 0。
当此对象不再被任何对象/过程引用,该指针会被 free 函数清理。

Data_Make_Struct(klass, type, mark, free, sval)

该宏用 malloc() 申请内存,分配给 sval 并返回封装好的 DATA。

Data_Get_Struct(data, type, sval)

该宏从 DATA 中取得指针,分配给 sval。

** 检查数据类型

TYPE(value)
FIXNUM_P(value)
NIL_P(value)
void Check_Type(VALUE value, int type)
void Check_SafeStr(VALUE value)

** 数据类型转换

FIX2INT(value)
INT2FIX(i)
NUM2INT(value)
INT2NUM(i)
NUM2DBL(value)
rb_float_new(f)
STR2CSTR(value)
rb_str_new2(s)

** 定义 类/模块

VALUE rb_define_class(const char *name, VALUE super)

定义一 super 的子类。

VALUE rb_define_class_under(VALUE module, const char *name, VALUE super)

在一模块的命名空间下新建一 super 的子类。

VALUE rb_define_module(const char *name)

定义一模块。

VALUE rb_define_module_under(VALUE module, const char *name, VALUE super)

在一模块的命名空间下新建一模块。

void rb_include_module(VALUE klass, VALUE module)

将一模块包含于一类。略已含。

void rb_extend_object(VALUE object, VALUE module)

将一模块的属性拓展给一对象。

** 定义全局变量

void rb_define_variable(const char *name, VALUE *var)

定义一 C 和 Ruby 共享的全局变量。若变量名中含有 symbol 不允许的字符,则该变量从 Ruby 程序中不可见。

void rb_define_readonly_variable(const char *name, VALUE *var)

定义只读全局变量。

void rb_define_virtual_variable(const char *name,
                                 VALUE (*getter)(), VALUE (*setter)())

定义一虚拟变量,其行为由一对 C 函数定义。变量被读/写时 getter/setter 会被调用。函数原型为:

        VALUE getter(ID id)
        void setter(VALUE val, ID id)

getter 函数必须返回一个值作为读的结果。

void rb_define_hooked_variable(const char *name, VALUE *var,
                                VALUE (*getter)(), VALUE (*setter)())

定义钩子变量。其为 C 共享的虚拟变量。getter 调用形式为:

        VALUE getter(ID id, VALUE *var)

返回一新值.  setter 调用形式为

        void setter(VALUE val, ID id, VALUE *var)

GC 要求 C 引用 Ruby 值的全局变量被标记。

void rb_global_variable(VALUE *var)

告诉 GC 保护这些变量

** 常量定义

void rb_define_const(VALUE klass, const char *name, VALUE val)

在一类/模块下定义一常量

void rb_define_global_const(const char *name, VALUE val)

定义全局常量.  这和以下等价:

     rb_define_const(cKernal, name, val)

** 方法定义

rb_define_method(VALUE klass, const char *name, VALUE (*func)(), int argc)

定义一类的方法。func 是函数指针。argc 是参数个数。若为 -1,函数会收到三个参数: argc, argv, self。
若为 -2,函数会收到两个参数: self, argv,这里 argv 是一个由方法参数组成的 Ruby 数组。

rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(), int argc)

定义一类的私有方法。参数同上。

rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(), int argc)

定义单体方法,参数同上。

rb_scan_args(int argc, VALUE *argv, const char *fmt, ...)

从 argc, argv 取得参数。fmt 是参数的格式字符串如"12"表示一个必须的参数和两个可选的参数。若"*"在 fmt 的末尾,
表示剩余的参数分配给对应的变量。

** 触发 Ruby 方法

VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)

触发一方法。用 rb_intern() 取得一方法名的 mid。

VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)

触发一方法,通过数组传参。

VALUE rb_eval_string(const char *str)

即 eval 的 C 版本。

ID rb_intern(const char *name)

返回 name 对应的 ID。

char *rb_id2name(ID id)

返回 ID 对应的名字。

char *rb_class2name(VALUE klass)

返回类名。

int rb_respond_to(VALUE object, ID id)

若对象会回应由 id 指定的信息则返回 true。

** 实例变量

VALUE rb_iv_get(VALUE obj, const char *name)

取得实例变量的值。若变量名称前缀非`@',则此变量从 Ruby 不可访问。

VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)

赋值给实例变量。

** 控制结构

VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)

调用函数 func1,并将 func2 作为块。func1 带着参数 arg1 调用。func2 接收两个参数,一是 yield 来的,二是 arg2。

VALUE rb_yield(VALUE val)

带着 val 执行块。

VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)

以 arg1 为参调用函数 func1。若异常产生,以 arg2 为参调用 func2。无异常则返回值由 func1 产生,否则由 func2 产生。

VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)

以 arg1 为参调用函数 func1,然后以 arg2 为参调用 func2 若执行中断。返回值由 func1 产生。

** 异常和错误

void rb_warn(const char *fmt, ...)

以 printf 的格式打印警告信息。

void rb_warning(const char *fmt, ...)

若 $VERBOSE 为真,以 printf 的格式打印警告信息。

void rb_raise(rb_eRuntimeError, const char *fmt, ...)

以 printf 格式引发 RuntimeError。

void rb_raise(VALUE exception, const char *fmt, ...)

以 printf 格式引发一类的异常。

void rb_fatal(const char *fmt, ...)

引发致命错误,并终止解释器。对于致命错误,没有异常处理机制,但是 ensure blocks 会被执行。

void rb_bug(const char *fmt, ...)

立即终止解释器。该函数应当在解释器产生由 bug 导致的情况时调用。异常处理机制或 ensure 都不会执行。

** 初始化及开始解释器

embedding API functions
下为嵌入 API 函数(拓展库不需要使用)

void ruby_init()

初始化解释器。

void ruby_options(int argc, char **argv)

处理解释器的命令行参数

void ruby_run()

开始解释器执行

void ruby_script(char *name)

指定脚本的名称 ($0)

附录 C. extconf.rb 中可用的函数
下面不翻了 没啥用[/fold]

假如有人成功把整个游戏的代码全翻译成 c 然后编译成 dll 了
脚本主体就只有两句
Win32API.new('s','Init','v','v').call
main
不知所以的人看到肯定是崩溃的
知道的人肯定更崩溃 什么人这么无聊...
梦石
0
星屑
163
在线时间
249 小时
注册时间
2014-7-18
回帖
26
发表于 2018-2-20 00:29:54 | 显示全部楼层
还是 Rubinius 实在点 (x
https://github.com/rubinius/rubinius

点评

win上明明暂时不实在 ( º﹃º ) 不过我真不知道它 学到了 :-)  发表于 2018-2-20 10:56
Role Play Games had saved me, but I can never save them.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部