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

Project1

 找回密码
 注册会员
搜索
楼主: 八云紫
打印 上一主题 下一主题

[RMVX发布] 新手教程--从0开始学RGSS2(2013-09-21 修复索引地址)

  [复制链接]

Lv1.梦旅人

梦石
0
星屑
50
在线时间
36 小时
注册时间
2008-2-22
帖子
35
131
发表于 2011-5-14 16:01:36 | 只看该作者
本帖最后由 芙兰朵露·斯卡雷特 于 2011-5-14 16:05 编辑

回复 一箭烂YiJL 的帖子

必然是顺序相关的, 次序也是需要对应的, 这个和数组一样, C 里纯的数组的地址是连续的, 序号 0 的地址 和 序号1 的地址总是相差一个类型的长度.


此外,  "p" 和 "l" 在传句柄的时候是一样的效果的. 句柄本身在 Window 里由句柄表来管理的, 我们拿到的, 貌似记得是 表里的索引.
回复 支持 反对

使用道具 举报

Lv4.逐梦者

弓箭手?剑兰

梦石
0
星屑
5344
在线时间
833 小时
注册时间
2010-11-17
帖子
1140
132
发表于 2011-5-14 16:04:53 | 只看该作者
回复 芙兰朵露·斯卡雷特 的帖子

嗯~反应很快哦。
不过C的结构体似乎很简洁,能够pack出一个Ruby的结构体么?(我想不大可能...)
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
36 小时
注册时间
2008-2-22
帖子
35
133
发表于 2011-5-14 16:06:42 | 只看该作者
回复 一箭烂YiJL 的帖子

Ruby 本身不就是有一个 Struct 类么? 用来处理结构体??

http://www.kuqin.com/rubycndocum ... _object_struct.html

这个有说明~~~
回复 支持 反对

使用道具 举报

Lv4.逐梦者

弓箭手?剑兰

梦石
0
星屑
5344
在线时间
833 小时
注册时间
2010-11-17
帖子
1140
134
发表于 2011-5-14 16:35:52 | 只看该作者
回复 芙兰朵露·斯卡雷特 的帖子

我怎么没有这回复帖的提醒呢?

Struct 类用法很像(不是生成子类的那部分),不过不能规定传入的类型。


比如有一个函数用了Ruby写的,要用其他语言结构Ruby的结构体似乎很难,
而且RGSS(?)的类像是将类藏在内存中,很难看出原型...
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
36 小时
注册时间
2008-2-22
帖子
35
135
发表于 2011-5-14 16:43:52 | 只看该作者
回复 一箭烂YiJL 的帖子

没收到回复估计是那个 审核 的问题.

Ruby 研究的不多. 找 紫苏大问问吧

点评

我后来看到回帖的称号很难看,于是注册了现在这个(第二个)。  发表于 2011-5-14 18:29
之前也不知道昵称是啥 = =  发表于 2011-5-14 17:30
这个ID曾经改过名?(我没有这么多V= =)  发表于 2011-5-14 17:26
像咱一样来改名吧~~~ > <  发表于 2011-5-14 17:17
我想删掉我的第一个ID,那个时候没分清楚"称号"和ID,搞得英文+数字= =  发表于 2011-5-14 17:01
回复 支持 反对

使用道具 举报

Lv1.梦旅人

风之塞尔达

梦石
0
星屑
50
在线时间
57 小时
注册时间
2005-10-22
帖子
2492

贵宾

136
发表于 2011-5-14 23:05:17 | 只看该作者
本帖最后由 link006007 于 2011-5-14 23:11 编辑

pack的本质就是将rb数组的内容,按照给定的格式转换成一个C二进制字符缓存(char*)。
以lz说的[5,6,7,8].pack("llll")为例,rb将数组的内容,按照‘l’表示的long型进行转换(4个l即4个元素都是long),然后将结果放入1个char*缓存中,效果类似
(*(long*)ptrBuf)++ = num2i32(rbNum)操作4次(ptrBuf应该会动态扩充到sizeof(long)*4),在ruby源码中是使用rb_str_buf_cat->str_buf_cat(str, ptr, len),其间多了很多复杂的检查和判断,不过最后一样也是memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);,最终效果和上述赋值一样。
这样形成的char*指向的内存结构恰巧和使用RECT来赋值是一样的。

'P'与'L'一样只限于32位API,在64位中,可能会发生指针截断。

要在其他语言调用ruby的结构和方法必须通过rb虚拟机提供的接口。和lua一样,虚拟机维护语言方法名或变量名到实际内部代码的映射,外部只能通过名称获取到该方法的调用或变量的值而不能直接访问。

以上,个人理解,有错不负责。。。
在程序里延续塞尔达的传说, 在画板上勾勒塞尔达的轮廓!!
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
137
发表于 2011-5-14 23:40:14 | 只看该作者
这两者的 内存映像 是相同的.

也要考虑数据结构对齐的问题。

  1. typedef struct cstruct_s {
  2.     int i;
  3.     short s;
  4. } cstruct;
复制代码
这样的一个结构体,在 ILP32 数据模型下,MSVC /Zp8 编译后的 sizeof (cstruct) 其实是 8。而 Ruby 的 String#pack 包装后的缓冲区却是:
  1. p [0, 0].pack("is") # => "x00x00x00x00x00x00"
复制代码
少了两个字节。如果这时候本地代码尝试访问 cstruct#s,就可能发生 segfault。MSVC 可以指定 /Zp2,即是用 2 个字节的界限来对齐内存,那样话的 sizeof (cstruct) 就可以是 6;GCC 也可以通过 __attribute__ ((aligned (x))) 来指定前面的结构体和联合体的对齐界限。

当然,Windows API 大多数情况下都是在和 32 位双字数据打交道,所以大部分结构都是 4 字节界限对齐的。

  显而易见的, 它是一个结构体, 里面的成员变量都是  long 类型的, 于是, 我们需要先创建一个这个结构体的实例:

RGSS2 代码:
lpRect = [0, 0, 0, 0].pack("llll")

如果涉及到的数据类型能大小是确定性的,这种简单的数据的结构就可以直接用字符串表示了:
  1. lpRect = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
复制代码
或是:
  1. lpRect = "\0\0\0\0" * 4
复制代码
这避免了 String#pack 的开销。32 位 Windows 采用的是 ILP32 数据模型,而 64 位 Windows 是 IL32P64(或者叫 LLP64),所以 long 类型在 Windows 下基本等同于 int  都是 32 位。只有在使用 LP64/ILP64 模型的系统下(比如 64 位 Linux),long 才是 64 位。


苏小脉于2011-5-15 01:57补充以下内容:
不过C的结构体似乎很简洁,能够pack出一个Ruby的结构体么?

理论上是可以的,只要你对特定 Ruby 实现的内部结构有足够的了解,就可以将所有需要的成员都集装到一个数组里,一并包装。这里之所以简洁完全是为了演示目的,教程一开始不需要太复杂的例子——C 结构当然也是可以很复杂的。

Ruby 本身不就是有一个 Struct 类么? 用来处理结构体??

Struct 类定义的是类的模版,可以想成是 Class 实例的工厂,和 C 结构体没有必然的关系。

比如有一个函数用了Ruby写的,要用其他语言结构Ruby的结构体似乎很难

写 Ruby 扩展就可以了。Ruby 提供了不少 C API 用于扩展 Ruby 语言。如果对细节有兴趣,可以参考 Dave Thomas 在《Programming Ruby》中给出的扩展教程

'P'与'L'一样只限于32位API,在64位中,可能会发生指针截断。


'P' 的话,如果是 32 位的 Ruby build,那确实。64 位的 build,本地指针应该就是按照 64 位来处理的了。

至于 'L',Windows 的本地 long 型永远都是 32 位,只是由于 Ruby 的 Fixnum 用了一位来表示直接值,所以 Fixnum 只能表示 2^31 个数。String#unpack 的时候会调用 num2i32(x),如果 x 超过了 Fixnum 所能表示的长度就会转换为 Bignum 返回给调用者:

  1. static unsigned long
  2. num2i32(x)
  3.     VALUE x;
  4. {
  5.     x = rb_to_int(x); /* is nil OK? (should not) */

  6.     if (FIXNUM_P(x)) return FIX2LONG(x);
  7.     if (TYPE(x) == T_BIGNUM) {
  8.         return rb_big2ulong_pack(x);
  9.     }
  10.     rb_raise(rb_eTypeError, "can't convert %s to `integer'", rb_obj_classname(x));
  11.     return 0;                   /* not reached */
  12. }
复制代码
如果要刻意使用 64 位整数,可以:
  1. p [ 2 ** 64 - 1, 2 ** 63 - 1 ].pack('Qq')
复制代码
这个就对对应 long long 型,只是它仅仅存在于 C99 中,不过大部分遵从 C89 的编译器都“部分支持”C99,其中泰半都有对 long long 的支持。

要在其他语言调用ruby的结构和方法必须通过rb虚拟机提供的接口。

(RM 嵌入的)MRI(Ruby 1.8 实现)没有虚拟机,只有 AST Walker。不过本地扩展的接口大致还是和其它版本一致的。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

风之塞尔达

梦石
0
星屑
50
在线时间
57 小时
注册时间
2005-10-22
帖子
2492

贵宾

138
发表于 2011-5-15 17:27:01 | 只看该作者
本帖最后由 link006007 于 2011-5-15 17:34 编辑

呃  可能说虚拟机不是恰当,那就说是解释器吧-  =
字节对齐是这样的,不过话说回来,NT6.1真是神一样的东西。。 除驱动外(和内核共用空间的原因么- =),x86程序几乎都可以平滑过渡到x64。相较linux,貌似就差很多

pack什么的理解成往一个刚好大小的内存缓冲区写入格式化过的数据就好了,剩下的,就是需要用pack'的同学怎么去组织自己数据然后交付给函数
在程序里延续塞尔达的传说, 在画板上勾勒塞尔达的轮廓!!
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
139
发表于 2011-5-16 02:05:03 | 只看该作者
回复 link006007 的帖子
呃  可能说虚拟机不是恰当,那就说是解释器吧-  =

但如果是针对 Ruby 1.9 说的话就很恰当了,嘿嘿。

NT6.1真是神一样的东西。。 除驱动外(和内核共用空间的原因么- =),x86程序几乎都可以平滑过渡到x64。相较linux,貌似就差很多

NT 6.0 以后,64 位驱动环境靠的是 64 位的 NTDLL.DLL,再往下已经没有兼容层了吧,肯定不能直接调用 32 位的子系统代码。用户空间的 32 位应用程序,要么直接被 CPU 硬件兼容,要么就是软件模拟兼容。NT 下兼容 32 位程序靠的是 WoW64,如果硬件支持 32 位指令集(比如 Intel 早期的 Pentium IV,Celeron D,当代的 Core 2/i3/i5/i7 都同时实现了 x86 和 x86-64),就只需要处理下程序入口点以及 32 位线程到 64 位线程的执行切换之类的;如果硬件不支持,那 WoW64 就得把 32 位指令翻译为 64 位指令。64 位 Linux 我没用过,不过 Linux 是最早把 64 位架构的长模式应用于实际的,不至于不能向下兼容 32 位程序啊。可能用于兼容的库默认没有和发行版一同推出?
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
36 小时
注册时间
2008-2-22
帖子
35
140
发表于 2011-5-16 11:16:02 | 只看该作者
看到 LS 两大触在讨论, 感觉压力很大.

之前一直不明白, 对齐是怎么一回事, 现在倒是了解大概意思了.

还有就是, 之前使用这个来调用 API , 但是老是出错, 求解释:

lprect = "\0" * 256
get_window_rect.call(hwnd, lprect)
lprect.delete("\0")
p lprect.unpack("l4")

是不是写法还是啥的问题?? 后来就直接先 pack 了~~
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-11-1 12:38

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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