Project1

标题: RGSS的C/C++扩展 [打印本页]

作者: guoxiaomi    时间: 2017-10-26 21:59
标题: RGSS的C/C++扩展
本帖最后由 RyanBern 于 2017-10-27 00:20 编辑

最近花了比较多的时间去思考用 C 扩展 ruby/rgss 的事情,也去各种奇怪的网站查找了很多的资料,最后却发现真正有用的东西居然就沉睡在这里:https://rpg.blue/thread-127979-1-1.html

之中的探索过程真的一言难尽,这里写一段 C++ 代码,表示一下我也是在努力着追寻大神们的脚步,但是似乎到此为止了……(遇到了太多的知识空白)
CPP 代码复制
  1. #include <windows.h>
  2. using namespace std;
  3.  
  4. static HMODULE hRGSSPatch = ::LoadLibraryA("RGSS102JPatch.dll");
  5. typedef unsigned long VALUE;
  6.  
  7. #define def(f, o, ...) \
  8. typedef o (*f##F) (__VA_ARGS__); \
  9. static f##F f = (f##F)::GetProcAddress(hRGSSPatch, #f);
  10.  
  11. // fetch function address from the Patch DLL.
  12. def(rb_define_module, VALUE, const char* name);
  13. def(rb_define_module_function, void, VALUE, const char*, VALUE, int);
  14. def(rb_num2ulong, unsigned long, VALUE);
  15.  
  16. // copy from ruby.h with a little change.
  17. #define FIX2INT(x) ((int)rb_num2ulong((VALUE)(x)))
  18.  
  19. #define RUBY_FIXNUM_FLAG 0x01
  20. #define RB_INT2FIX(i) (((VALUE)(i))<<1 | RUBY_FIXNUM_FLAG)
  21. #define INT2FIX(i) RB_INT2FIX(i)
  22.  
  23. #define RUBY_METHOD_FUNC(func) ((VALUE) (*func))
  24.  
  25. // dll export function
  26. extern "C" {
  27.         __declspec(dllexport) void Init_Test(void);
  28. }
  29.  
  30. VALUE add(VALUE self, VALUE a, VALUE b) {
  31.         int aa = FIX2INT(a);
  32.         int bb = FIX2INT(b);
  33.         return INT2FIX(aa + bb);
  34. }
  35.  
  36. void Init_Test(void) {
  37.         VALUE Test = rb_define_module("Test");
  38.         rb_define_module_function(Test, "add", RUBY_METHOD_FUNC(add), 2);
  39. }

用 g++ 编译后的DLL文件,可以用 Win32API 调用 Init_Test:
RUBY 代码复制
  1. Win32API.new('Test', 'Init_Test', 'v', 'v').call
  2. p Test.add(10, 20) #=> 30

当然,游戏的 Game.ini 设置必须是 102J.dll,我不知道为什么……
没有必要存在的东西


作者: SixRC    时间: 2017-10-27 00:54
点评原来有隐含的长度限制..
最近也有想着优化rgss的
不过能力不足 有了知识才好实践各种乱七八糟的想法
好想有大把时间拿来学习
虽然时间是有 不过却是拿来玩了..

作者: 余烬之中    时间: 2017-10-28 00:40
本帖最后由 余烬之中 于 2017-10-28 00:47 编辑

来了兴趣,折腾了一阵

以前只给 VA 写过 Bitmap 功能拓展之类的,完全用不上什么 rb_define_module
不过写起来倒也不难,毕竟半云都搞出了 ProjectGap,函数地址直接抄来就行了(由醋瞎黄姬友情提供)
搞了一下午+一晚上,其实主要时间都花在修玄学 msys2 的 mingw32 g++(并且没修好改用 msvc cl 了)

仍然是给 VA 写的,也没什么好解释的,还是一个雏形,只要能够给猫叔提供一点启发我就满足了(逃
编辑:RGSS301.dll,不过理论上自己能搞到函数地址的话通用(逃

未严格测试

CPP 代码复制
  1. // License: RBLv1(https://rpg.blue/thread-403387-1-1.html)
  2.  
  3. // headers
  4. #include <windows.h>
  5. #include <climits>
  6. #include <tchar.h>
  7.  
  8. // defines
  9. #define RGSSAPI extern "C" __declspec(dllexport)
  10. typedef unsigned long VALUE;
  11. typedef unsigned long ID;
  12. typedef long SIGNED_VALUE;
  13. #define RUBY_FIXNUM_FLAG 0x01
  14. #define Qfalse ((VALUE)0)
  15. #define QTrue  ((VALUE)2)
  16. #define Qnil   ((VALUE)4)
  17. #define Qundef ((VALUE)6)
  18. #define FIX2LONG(x)    ((long)(((SIGNED_VALUE)x)>>1))
  19. #define FIX2ULONG(x)   (((x>>1))&LONG_MAX)
  20. #define FIX2INT(x)     ((int)FIX2LONG(x))
  21. #define FIX2UINT(x)    ((unsigned int)FIX2ULONG(x))
  22. #define INT2FIX(i)     ((VALUE)(((SIGNED_VALUE)(i))<<1|RUBY_FIXNUM_FLAG))
  23. #define FIXNUM_MAX     ((unsigned long)(LONG_MAX>>1))
  24. #define FIXNUM_MIN     ((long)LONG_MIN>>(int)1)
  25. #define FIXNUM_P(x)    ((((SIGNED_VALUE)(x))&RUBY_FIXNUM_FLAG)!=0)
  26. #define POSFIXABLE(ul) (ul<=FIXNUM_MAX)
  27. #define NEGFIXABLE(l)  ( l>=FIXNUM_MIN)
  28. #define FIXABLE(l)     (NEGFIXABLE(l)&&(l<=0||POSFIXABLE(l)))
  29. #define def(func, ret, ...) typedef ret(*T##func)(__VA_ARGS__); T##func func
  30. //  function                   return type   arguments
  31. def(RGSSEval,                  int,          const char*);
  32. def(rb_define_module,          VALUE,        const char*);
  33. def(rb_define_module_function, void,         VALUE, const char*, void*, int);
  34. #undef def
  35.  
  36. // extension main
  37. VALUE add(VALUE self, VALUE a, VALUE b) {
  38.   return INT2FIX(FIX2INT(a)+FIX2INT(b));
  39. }
  40.  
  41. RGSSAPI void Test() {
  42.   VALUE Test = rb_define_module("Test");
  43.   rb_define_module_function(Test, "add", add, 2);
  44. }
  45.  
  46. // Initialize
  47. void Initialize() {
  48.   HMODULE hRGSSLIB;
  49.   TCHAR PATH[MAX_PATH];
  50.   TCHAR RGSSLIB[MAX_PATH];
  51.   GetCurrentDirectory(MAX_PATH, PATH);
  52.   _tcsncat_s(PATH, MAX_PATH, _T("\\Game.ini"), MAX_PATH);
  53.   GetPrivateProfileString(_T("Game"), _T("Library"), NULL, RGSSLIB, MAX_PATH, PATH);
  54.   hRGSSLIB = GetModuleHandle(RGSSLIB);
  55. #define setproc(proc, func) func = (T##func)GetProcAddress(hRGSSLIB, #proc)
  56. #define setaddr(addr, func) func = (T##func)((DWORD)addr+(DWORD)hRGSSLIB)
  57.   // set function
  58.   setproc(RGSSEval, RGSSEval);
  59.   setaddr(0x5E990, rb_define_module);
  60.   setaddr(0x5F1E0, rb_define_module_function);
  61. #undef setaddr
  62. #undef setproc
  63. }
  64.  
  65. class Init {
  66. public:
  67.   Init() {
  68.     Initialize();
  69.   }
  70. } init;

作者: 浮云半仙    时间: 2017-10-28 10:12
瑟瑟发抖,留下沟中的项目地址:gitHub.com/sxysxy/ProjectGap
[del]应该是比较科学的给rgss写c扩展的方法,也不需要魔改原有的二进制文件。[/del]





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