设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2137|回复: 5
打印 上一主题 下一主题

[有事请教] Ruby跟C语言交互的时候,只使用单数,那不是很浪费么。

[复制链接]

Lv1.梦旅人

梦石
0
星屑
50
在线时间
130 小时
注册时间
2010-6-26
帖子
404

第5届短篇游戏比赛季军

跳转到指定楼层
1
发表于 2011-8-20 17:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 尘羽泯 于 2011-8-20 17:13 编辑
  1. /* special contants - i.e. non-zero and non-fixnum constants */
  2. #define Qfalse ((VALUE)0)
  3. #define Qtrue  ((VALUE)2)
  4. #define Qnil   ((VALUE)4)
  5. #define Qundef ((VALUE)6)        /* undefined value for placeholder */
复制代码
以上是ruby.h里面定义的四个常量。
于是我就生了问题,当传递Integer的时候,如果恰好传2,那么不是会变成True么?可是Ruby里面2==true显然不可能成立。
下面我用rb_define_global_function定义了一个函数,
VALUE a(VALUE b){
MessageBox(char(b),0,"")
return b
};

在C语言与Ruby交互的时候终于找到了规律
下面是Ruby代码:
print a 0 #=>C的MessageBox显示1,Ruby的print显示0
print a 1 #=>C的MessageBox显示3,Ruby的print显示1
print a 2#=>C的MessageBox显示5,Ruby的print显示2
print a 3#=>C的MessageBox显示7,Ruby的print显示3
print a 4#=>C的MessageBox显示9,Ruby的print显示4
print a 5#=>C的MessageBox显示11,Ruby的print显示5
于是我知道了。Ruby里面的Integer变量,到了C里面,都会变成单数,双数用来定义false、true、nil等特殊的类型,这样就可以区别nil、false、true和普通的Integer。

不过,这样子的话。32位的有符号整数,去掉了一半用来存这仅仅4个类型,Ruby这样做,是不是很失败呢。那不是很浪费么?而且。取值范围也减少了一半。


尘羽泯于2011-8-20 17:33补充以下内容:
哦哦,我知道了,Ruby里面的String、Array等类型,传递到C里面,也是一个双数的指针,这样就可以区别变量类型了。单数是Integer,把(它-1)/2就可以得到Ruby里面传过来的值,双数的话0、2、4、6分别代表特定的4种类型,再大一点就是内存指针,可能是Strng或Array什么的。
Fijoy游戏引擎:http://www.fijoy.com/

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
41121
在线时间
7568 小时
注册时间
2009-7-6
帖子
13498

开拓者贵宾

2
发表于 2011-8-20 18:03:13 | 只看该作者
我想知道你知道单数是什么意思吗?
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

Lv2.观梦者

傻♂逼

梦石
0
星屑
374
在线时间
1606 小时
注册时间
2007-3-13
帖子
6562

烫烫烫开拓者

3
发表于 2011-8-20 18:06:02 | 只看该作者
= =这是 Ruby的储存方式把

点评

嗯。确实。Ruby的变量在内存中的储存方式应该就是如此。不然的话只能每个变量都是一个结构体指针,专门弄一个Int来记录变量类型,太浪费内存。  发表于 2011-8-20 19:04
哎呀,蛋疼什么的最有爱了
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1150
在线时间
1564 小时
注册时间
2008-7-30
帖子
4418

贵宾

4
发表于 2011-8-20 19:14:43 | 只看该作者
Fixnum 类表示小整数,由 INT2FIX 得到。由于可能在程序中频繁使用,将其用结构体表示可能会使执行速度大打折扣,因此直接嵌入 VALUE 中。数值左移一位或上0x01使得 Fixnum总是一个奇数,其实际可用比特位为 sizeof(long)*8-1 ,可表示的最大最小值分别为FIXNUM_MAX 和 FIXNUM_MIN ,超出该范围的数属于 Bignum 类,由C结构体实现。


http://www.ibm.com/developerworks/cn/opensource/os-cn-rubysbl2/

点评

原来是这样。呃哈。了解了。  发表于 2011-8-20 19:22

See FScript Here:https://github.com/DeathKing/fscript
潜心编写URG3中。
所有对URG3的疑问和勘误或者建议,请移步至发布页面。
欢迎萌妹纸催更
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
5
发表于 2011-8-20 23:53:16 | 只看该作者
本帖最后由 苏小脉 于 2011-8-21 00:04 编辑
Ruby里面的String、Array等类型,传递到C里面,也是一个双数的指针,这样就可以区别变量类型了

不仅是“双数”而已,在当代的 32 位机下,指针的存储永远是在一个长度为 4 字节以上的界限内 [1],如此一来指针的两个最低的有效位可以保证为 0,也就是整个指针存储的数据永远是 4 的倍数。CRuby 实现就依赖了这个事实,当这两个位有一个位为 1 时,当前的 VALUE 就是直接值,而不是对象指针。

Ruby里面的Integer变量,到了C里面,都会变成单数,双数用来定义false、true、nil等特殊的类型,这样就可以区别nil、false、true和普通的Integer。

“单数”、“双数”这样的说法容易引起歧义,不够严谨。CRuby 目前是这样实现的:

VALUE 最低有效位如果为 1,则为 Fixnum,Fixnum 的值存储在其余 31 位中,故右移一位可得。

0 = 0b0000,2 = 0b0010,4 = 0b0100,6 = 0b0110
这里面 2 和 6 由于第二最低有效位为 1,所以肯定是直接值;0 和 4 虽然刚好在 4 的界限上,但在当代的 OS 下属于 OS 保留字段,不可能成为虚拟地址,故而这些都可以用来存储直接值。

Symbol 也是直接值,但却是用的最低有效字节(8 个位)来标识。如果最低有效字节 = 0x0e = 0b00001110,那么最高 24 位就是 Symbol 的 ID,故通过左移、右移 8 位可互换。

不过,这样子的话。32位的有符号整数,去掉了一半用来存这仅仅4个类型,Ruby这样做,是不是很失败呢。

目前 CPython 实现也是采取的这个路子。若果不这么做,直接值就须得动态分配或是使用 tagged 结构联合。通常动态内存分配的效率自然是不及静态内存拷贝的,在大部分 C 实现下,前者要经过堆的统一管理,而后者只是简单的栈操作;tagged 结构联合虽然不需要动态分配,但每次都依靠函数传值,这个拷贝过程也是昂贵的,还别提 tagged 联合的内存泄漏问题最容易被忽视。实际上目前这种 VALUE 存储方式就是 tagged 联合的一种,只不过巧妙地避免了不必要的开销。

而且。取值范围也减少了一半。

当需要和大于 2^30-1 的数打交道时,各种运算的操作只怕轻易就超过 32 位整数范围了,横竖动态语言支持 Bignum,怕他作甚。

[1] 64 位编译环境下界限为  8 字节。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
130 小时
注册时间
2010-6-26
帖子
404

第5届短篇游戏比赛季军

6
 楼主| 发表于 2011-8-21 06:26:48 | 只看该作者
本帖最后由 尘羽泯 于 2011-8-21 09:26 编辑
苏小脉 发表于 2011-8-20 23:53
不仅是“双数”而已,在当代的 32 位机下,指针的存储永远是在一个长度为 4 字节以上的界限内 [1],如此一 ...


膜拜紫苏帝,见到紫苏帝,我的眼泪就止不住汪汪地掉。


VALUE 最低有效位如果为 1,则为 Fixnum,Fixnum 的值存储在其余 31 位中,故右移一位可得。

看到这里,我终于知道了我有多傻
(伪代码:)
Integer Fixnum2Integer(VALUE fix){
___asm("
mov eax,[ebp+8]
dec eax
shr eax,1
leave
ret 4
")}
右移之后,最低位本来就没了,我竟然傻乎乎的在前面dec - -b 啊啊啊。

Symbol 也是直接值,但却是用的最低有效字节(8 个位)来标识。

Ruby都忘得差不多啦,Symbol是啥玩意儿都给忘了。(好像原来也不曾知道过,貌似是符号- -b)
  1. To convert C data to Ruby values:

  2. FIXNUM  left shift 1 bit, and turn on LSB.  
复制代码
这个是网上看到的一段注释,不过不懂turn on LSB是啥。
----------
感谢紫苏的热情解答(注释也很可爱 - -b)。不过。我发现,紫苏是神啊,从不曾睡觉(从23点,到5点,这段时间,一直有发帖呢)。

点评

老板不在天朝的说……当然“不曾睡觉”  发表于 2011-8-21 09:43
Fijoy游戏引擎:http://www.fijoy.com/
回复 支持 反对

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-9-27 22:37

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表