Project1

标题: 问几个涉及到Ruby底层的问题…… [打印本页]

作者: zh99998    时间: 2009-3-8 15:15
标题: 问几个涉及到Ruby底层的问题……
所谓底层是相对于RGSS……也就是Ruby层

1.怎么保存运行环境(保存所有object),并且在对象发生了改变后可以还原
  也就是相当于即时存档吧
2.怎么获取caller对象,默认的caller只能获取代码页、行数和方法名,不能获取调用者对象
[LINE]1,#dddddd[/LINE]
错误日志
http://rpg.blue/viewthread.php?tid=78782&ntime=2009%2D3%2D8+20%3A38%3A42
即时存档……跟本帖的要求不一样
http://rpg.blue/viewthread.php?tid=118882&ntime=2009%2D3%2D8+20%3A50%3A21 [LINE]1,#dddddd[/LINE]版务信息:版主帮忙结贴~
作者: link006007    时间: 2009-3-9 01:05
写文档和winAPI都已经忘光了阿...{/gg}

caller是什么  ruby 的 backtrace?
作者: 淘金鸭    时间: 2009-3-9 01:29
在RUBY里咋用API?
作者: jzly007    时间: 2009-3-9 02:05
这个问题看的我很迷茫~
作者: zh99998    时间: 2009-3-9 02:26
以下引用link006007于2009-3-8 17:05:35的发言:

写文档和winAPI都已经忘光了阿...

caller是什么  ruby 的 backtrace?

以下引用淘金鸭于2009-3-8 17:29:50的发言:

在RUBY里咋用API?

Win32API.new

作者: link006007    时间: 2009-3-9 03:53
在ruby自带的backtrace中, 出错是可以获取出错的类的名称的 ..。 但是这些不属于backtrace
如果是要出错的类实例化的对象的变量名的话。。 ms需要自己修改ruby源码了{/gg}

VC++
#define DEFS_ERRORMSG_LEN_CHAR 256
... ...
static char pOut[DEFS_ERRORMSG_LEN_CHAR];
... ...
VALUE lasterr                  = rb_gv_get("$!");

VALUE klass                    = rb_class_path(CLASS_OF(lasterr));

VALUE message                  = rb_obj_as_string(lasterr);
::sprintf_s(pOut, DEFS_ERRORMSG_LEN_CHAR, "\nErrorType:\n\t%s \nMessage:\n\t%s\n", RSTRING(klass)->ptr, RSTRING(message)->ptr);
if(!NIL_P(ruby_errinfo)) {
    VALUE ary                  = rb_funcall(ruby_errinfo, rb_intern("backtrace"), 0);
    ... ...
    ... ...
作者: zh99998    时间: 2009-3-9 04:38
不一定要出错呀,错误记录已经有了哦
http://rpg.blue/viewthread.php?tid=78782&ntime=2009%2D3%2D8+20%3A38%3A42
不过我看不太懂
作者: 尤莉斯    时间: 2009-3-9 19:47
1 、你先考虑好还原时候程序的切入点吧,从什么地方开始还原。。 (用ObjectSpace)可以获取所有对象。。。
2、问题无效。。= = 略过
3、很显然的API问题,一可以直接使用API创建窗口,二是用DLL封装窗口rgss调用接口
4、receiver、context和binding
    receiver 方法的接受者 obj.clone # 这里obj可以理解为receiver
    context  执行环境的上下问,就理解为保存了程序执行环境的一些信息 比如 局部变量等。。
    binding一般和eval连用,banding一个上下文,可以作为eval的运行环境, 比如有的时候
   eval("p a") 如果这里a是局部变量则eval的环境无法访问,可以用绑定当前环境传递给eval运行= =
作者: 沉影不器    时间: 2009-3-11 01:45
提示: 作者被禁止或删除 内容自动屏蔽
作者: zh99998    时间: 2009-3-13 20:43
以下引用尤莉斯于2009-3-9 11:47:03的发言:
用ObjectSpace可以获取所有对象。。。

以下引用沉影不器于2009-3-10 17:45:45的发言:
2 caller...这函数本来就只返回这三个东西...您打算从caller获得RTP内部类的代码?我觉得松本先生不那么傻...

否,只要得到那个实例就可以了,不是要代码

以下引用沉影不器于2009-3-10 17:45:45的发言:
3 CreateWindowEx我还没用纯api创建过那么复杂的窗体...是自找苦

在RM里 除了API还有别的办法创建窗体?
作者: 亿万星辰    时间: 2009-3-15 19:49
获取当前实例?self?
作者: zh99998    时间: 2009-3-15 23:59
不是当前实例,是调用当前方法的那个实例
作者: 亿万星辰    时间: 2009-3-17 00:44
有点理解不了了,能举例说明一下么
作者: 八云紫    时间: 2009-3-17 05:52
http://book.51cto.com/art/200711/60797.htm

使用到 FOX , GTK 什么的~ [LINE]1,#dddddd[/LINE]系统信息:本贴由本区版主认可为正确答案,66RPG感谢您的热情解答~
作者: 美兽    时间: 2009-3-17 16:14
第三个:
CreateWindow
GetWindowLong
SetWindowTxt
作者: zh99998    时间: 2009-3-17 20:46
以下引用亿万星辰于2009-3-16 16:44:23的发言:

有点理解不了了,能举例说明一下么

class A
  def initialize
    B.new
  end
end
class B
  def initialize
    #在这里获取调用者,应该是$a
  end
end
$a = A.new

其中B类是自己定义的,A类和$a = A.new都是已经写好,不能更改不知内容的,只能确定A类的实例生成并且调用了B的initialize
作者: zmv2000a    时间: 2009-3-17 20:54
以下引用zh99998于2009-3-13 12:43:18的发言:


以下引用尤莉斯于2009-3-9 11:47:03的发言:
用ObjectSpace可以获取所有对象。。。



以下引用沉影不器于2009-3-10 17:45:45的发言:
2 caller...这函数本来就只返回这三个东西...您打算从caller获得RTP内部类的代码?我觉得松本先生不那么傻...


否,只要得到那个实例就可以了,不是要代码


以下引用沉影不器于2009-3-10 17:45:45的发言:
3 CreateWindowEx我还没用纯api创建过那么复杂的窗体...是自找苦

在RM里 除了API还有别的办法创建窗体?

有,不用RM也可以创建窗体,别以为这是一句废话,体会一下。难道做游戏非要用Rm吗?
作者: 八云紫    时间: 2009-3-17 21:04
以下引用zh99998于2009-3-17 12:46:06的发言:

class A
def initialize
   B.new
end
end
class B
def initialize
   #在这里获取调用者,应该是$a
end
end
$a = A.new

其中B类是自己定义的,A类和$a = A.new都是已经写好,不能更改不知内容的,只能确定A类的实例生成并且调用了B的initialize


$a = A.new

这句话有问题。

要使用 $a ,就必须先赋值 $a, 但是这里的 $a 的赋值明显的要比 A 的实例化要后一步才执行。 即使能调用 $a ,也只能读出 nil 罢了。
作者: 八云紫    时间: 2009-3-17 21:06
这个就是变量是先定义后使用还是先使用后定义的问题。
作者: zh99998    时间: 2009-3-17 21:09
以下引用火焰猫燐于2009-3-17 13:06:25的发言:
$a = A.new

这句话有问题。

要使用 $a ,就必须先赋值 $a, 但是这里的 $a 的赋值明显的要比 A 的实例化要后一步才执行。 即使能调用 $a ,也只能读出 nil 罢了。


那么应该是说,读出A.new,就是$a代表的那个实例,所以有没有被赋值都无所谓
作者: 八云紫    时间: 2009-3-17 21:11
以下引用zh99998于2009-3-17 13:09:27的发言:

那么应该是说,读出A.new,就是$a代表的那个实例,所以有没有被赋值都无所谓


怎么说,反正是调用不了 $a 。使用匿名类的话,没有什么意义。
作者: zh99998    时间: 2009-3-17 21:15
要获取的是那个【实例】,就是【#<A:0x********>】至于匿名问题,只要能引用到了随便抓个变量给赋值就可以了
作者: 八云紫    时间: 2009-3-17 21:16
以下引用zh99998于2009-3-17 13:15:32的发言:

要获取的是那个【实例】,就是【#<A:0x********>】至于匿名问题,只要能引用到了随便抓个变量给赋值就可以了


都说了,按你的写法, 获取不了。

换个写法才可以。
作者: zh99998    时间: 2009-3-17 21:18
那要怎么写呢?
(A是不能更改的,B可以正在写的)
作者: 八云紫    时间: 2009-3-17 21:19
以下引用zh99998于2009-3-17 13:18:33的发言:

那要怎么写呢?
(A是不能更改的,B可以正在写的)


A 不能更改,但是 Ruby 的 class 是可以添加属性的,自己添一个去。
作者: zh99998    时间: 2009-3-17 21:23
谢……虽然还是不明白……
作者: zmv2000a    时间: 2009-3-17 21:26
以下引用zh99998于2009-3-17 13:23:21的发言:

谢……虽然还是不明白……


面向对象的思想哪这么容易理解啊,很抽象的,慢慢学吧。

作者: 八云紫    时间: 2009-3-17 21:26
以下引用zh99998于2009-3-17 13:23:21的发言:

谢……虽然还是不明白……


class A
  def initialize
    @number = 1
  end
end

class A
  attr_accessor :number  
end

p A.new.number

作者: 亿万星辰    时间: 2009-3-18 01:40
以下引用火焰猫燐于2009-3-17 13:26:19的发言:
class A
def initialize
   @number = 1
end
end

class A
attr_accessor :number  
end

p A.new.number

这个当然没问题了,按我的理解,在编译的过程中,就已经把这些对同一个类的各段代码整合到一起了。
作者: 八云紫    时间: 2009-3-18 02:06
恩。

感觉编译器会先扫描一遍,查查错误,合并一下同名类什么的,大概~
作者: 尤莉斯    时间: 2009-3-18 16:20
以下引用zh99998于2009-3-17 12:46:06的发言:


以下引用亿万星辰于2009-3-16 16:44:23的发言:

有点理解不了了,能举例说明一下么


class A
def initialize
   B.new
end
end
class B
def initialize
   #在这里获取调用者,应该是$a
end
end
$a = A.new

其中B类是自己定义的,A类和$a = A.new都是已经写好,不能更改不知内容的,只能确定A类的实例生成并且调用了B的initialize


不可能!! ~ ruby =号不可能获取到 左值的。。
作者: zh99998    时间: 2009-3-18 20:30
…………………………………………
貌似我的表达能力差到一定境界了
  1. class B
  2.   def initialize(obj)
  3.     $obj = obj
  4.     p $obj
  5.   end
  6. end
  7. class A
  8.   def initialize
  9.     B.new(self)
  10.   end
  11. end
  12. $a = A.new
复制代码
这样写,能输出 #<A:0x30edeb8>

但是现在A类已经定义好了,不能再修改,里面调用B的时候并没有把self传递下去
  1. class A
  2.   def initialize
  3.     B.new
  4.   end
  5. end
复制代码
要怎样定义B才能获取那个已经生成了的A的实例,即 #<A:0x30edeb8>
作者: 八云紫    时间: 2009-3-18 20:45
class A
  attr_accessor :timer                  
  def initialize
    @timer = 1
  end
end
class A
def geta(a)
   B.new(a)
end
end
class B
def initialize(callers)
   p callers
end
end
a = A.new
p a
a.geta(a)

不知道你到底想做什么。 如果行不通,90% 是算法的问题。
作者: 八云紫    时间: 2009-3-18 20:46
测试过了,内存指针指向同一个地址。

---------------------------
Project1
---------------------------
#<A:0x2c611a8 @timer=1>
---------------------------
确定   
---------------------------

[LINE]1,#dddddd[/LINE]
---------------------------
Project1
---------------------------
#<A:0x2c611a8 @timer=1>
---------------------------
确定   
---------------------------

作者: zh99998    时间: 2009-3-18 20:48
嗯……caller只能获得方法名,行号,和文件名,不能获取实例
B.new(a)
A类是已经定义好不能更改的,或者说不知道A里面是怎么定义的,它调用B的时候并没有把自己作为参数传递下去
作者: 八云紫    时间: 2009-3-18 20:49
以下引用zh99998于2009-3-18 12:48:36的发言:

嗯……caller只能获得方法名,行号,和文件名,不能获取实例


看清楚,那个不是方法,是局部变量
作者: 八云紫    时间: 2009-3-18 20:52
以下引用zh99998于2009-3-18 12:48:36的发言:

A类是已经定义好不能更改的,或者说不知道A里面是怎么定义的,它调用B的时候并没有把自己作为参数传递下去


你就不能自己定义一个方法吗?
类里又不是不准追加定义。
作者: zh99998    时间: 2009-3-18 20:54
因为不知道A里的那个方法是怎么定义的,所以不能改它
作者: 八云紫    时间: 2009-3-18 20:54
以下引用zh99998于2009-3-18 12:54:02的发言:

因为不知道A里的那个方法是怎么定义的,所以不能改它


你到底是想要把 A 里方法套出来,还是要拿到 A 的某个实例?
作者: zh99998    时间: 2009-3-18 20:55
是要拿到A的实例
(A里的方法也是未知的,但是需要拿到代码)
作者: 八云紫    时间: 2009-3-18 20:55
我之前发的那个不就是拿到了 A 的实例。内存地址都一样。
作者: zh99998    时间: 2009-3-18 20:56
你那个里面有
class A
def geta(a)
  B.new(a)
end
end
那么A里原来的调用B类的定义就被破坏了
作者: 八云紫    时间: 2009-3-18 20:58
以下引用zh99998于2009-3-18 12:56:47的发言:
那么A里原来的调用B类的定义就被破坏了


啥意思? A 里定义了 B 类?
作者: zh99998    时间: 2009-3-18 20:58
A里生成和调用了B类
就像Scene_Equip和Window_Equip
作者: 八云紫    时间: 2009-3-18 20:59
以下引用zh99998于2009-3-18 12:58:28的发言:

A里生成和调用了B类


怕被破坏,就用继承。
作者: zh99998    时间: 2009-3-18 21:07
A和B就像Scene_Equip和Window_Equip的关系
作者: 八云紫    时间: 2009-3-18 21:09
以下引用zh99998于2009-3-18 13:07:40的发言:

A和B就像Scene_Equip和Window_Equip的关系


有啥区别,感觉我之前的那个方法没啥问题。
作者: zh99998    时间: 2009-3-18 21:10
就是Scene_Equip里调用Window的方法不知道,所以不能改Scene里的方法哦
作者: 八云紫    时间: 2009-3-18 21:14
不能呢个自己添加一个吗?
作者: zh99998    时间: 2009-3-18 21:16
添加一个没用的啊,自己添加的又不会被系统调用
作者: 八云紫    时间: 2009-3-18 21:23
不能手动调用?
作者: zh99998    时间: 2009-3-18 21:25
不能的哦,要获取的就是系统正在运行中的那个实例
作者: 八云紫    时间: 2009-3-18 21:29
系统正在运行中的那个实例 ?
内存一样的话,实例就是一样的吧。
作者: zh99998    时间: 2009-3-18 21:31
对呀,如果手动调用的话,要么就读到系统生成的那个实例,否则就只能新生成实例咯

问获取调用者实例的目的就是要调用那个实例哦
作者: 八云紫    时间: 2009-3-18 21:32
以下引用zh99998于2009-3-18 13:31:40的发言:

对呀,如果手动调用的话,要么就读到系统生成的那个实例,否则就只能新生成实例咯

问获取调用者实例的目的就是要调用那个实例哦


不是吧,内存一样的话,是按地址传递参数的~ [LINE]1,#dddddd[/LINE]系统信息:本贴由本区版主认可为正确答案,66RPG感谢您的热情解答~
作者: 沉影不器    时间: 2009-3-28 05:27
提示: 作者被禁止或删除 内容自动屏蔽
作者: zh99998    时间: 2009-3-28 20:55
以下引用沉影不器于2009-3-27 21:27:26的发言:


以下引用美兽于2009-3-17 8:14:36的发言:

第三个:
CreateWindow
GetWindowLong
SetWindowTxt


标题栏那个...可能是mouse_action..难做..
其它讨论内容...实在太长了没看下去.....


上面的讨论结果是,可以利用Ruby附加库
作者: zh99998    时间: 2009-6-12 08:00
顶起……
作者: 猫哥哥    时间: 2009-7-3 14:19
本帖最后由 猫哥哥 于 2009-7-3 14:38 编辑
class A
  def initialize
    B.new
  end
end
class B
  def initialize
    #在这里获取调用者,应该是$a
  end
end
$a = A.new

其中B类是自己定义的,A类和$a = A.new都是已经写好,不能更改不知内容的,只能 ...
zh99998 发表于 2009-3-17 20:46


那个……与其考虑怎么从class B获得A的实例,还不如直接从class A下手呢-_-|||

虽然不知道class A在其内部是怎么处理的,但既然class A也是一个类,它就有initialize,那么就通过alias定义
  1. class A

  2. alias:old_init initialize
  3. def initialize
  4.     $a = self
  5.     old_init
  6. end

  7. end
复制代码
$a 就是生成的那个实例了。

为了看这个能不能用我还特意试验了一下:
  1. class A
  2.   attr_accessor:vv
  3.   
  4.   def initialize
  5.     $a = self
  6.   end
  7.   
  8. end

  9. aa = A.new
  10. aa.vv = 6

  11. p $a.vv   #=>输出 6
  12. exit
复制代码
所以感觉没有必要考虑class A在initialize以后还会怎么处理或者变化,因为$a会像指针一样一直指向这个实例(不知道把$a比喻成一个指针是否恰当-_-|||)。
-------------------------------------------------------------------------------------

如果想实现的是即时存档,也没必要把所有的object都保存了呀。只要存储一些会有变动的变量和object(在制作游戏的时候就设计好)通过marshal序列化存起来,其他的object照着存储的变量再临时生成就行了。

RGSS的储存方式也是这么做的。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1