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

Project1

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

[交流讨论] 在RMVA使用Fiddle代替win32api

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1046
在线时间
166 小时
注册时间
2025-5-6
帖子
22
跳转到指定楼层
1
发表于 2026-4-26 00:09:04 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

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

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

x
  1. #===============================================================
  2. # Vx ace  Fiddle
  3. #
  4. #===============================================================
  5. module Fiddle
  6.   
  7.   TYPE_VOID   = DL::TYPE_VOID
  8.   TYPE_INT    = DL::TYPE_INT
  9.   TYPE_LONG   = DL::TYPE_LONG
  10.   TYPE_VOIDP  = DL::TYPE_VOIDP
  11.   TYPE_FLOAT  = DL::TYPE_FLOAT
  12.   TYPE_DOUBLE = DL::TYPE_DOUBLE
  13.   TYPE_CHAR   = DL::TYPE_CHAR
  14.   TYPE_SHORT  = DL::TYPE_SHORT
  15.   TYPE_UCHAR  = -TYPE_CHAR
  16.   TYPE_USHORT = -TYPE_SHORT
  17.   TYPE_UINT   = -TYPE_INT
  18.   TYPE_ULONG  = -TYPE_LONG
  19.   #调用约定
  20.   DEFAULT = :stdcall

  21.   #========== 函数封装 ==========
  22.   class Function
  23.     def initialize(ptr, args, ret, abi = DEFAULT)
  24.       @ptr  = ptr
  25.       @args = args
  26.       @ret  = ret
  27.       @calltype = case abi
  28.                   when :stdcall, :STDCALL, 1 then :stdcall
  29.                   when :cdecl,   :CDECL,   0 then :cdecl
  30.                   else :stdcall
  31.                   end
  32.       @cfunc = DL::CFunc.new(ptr, ret, 'fiddle_func', @calltype)
  33.     end

  34.     def call(*args)
  35.       temp_ptrs = []
  36.       converted = args.zip(@args).map do |val, type|
  37.         if type == TYPE_VOIDP
  38.           if val.nil?
  39.             0
  40.           elsif val.is_a?(String)
  41.             #转为 UTF-16LE(Unicode)
  42.             utf16 = val.encode("UTF-16LE") + "\0\0".encode("UTF-16LE")
  43.             bin = utf16.force_encoding("ASCII-8BIT")
  44.             ptr = DL::CPtr[bin]
  45.             temp_ptrs << ptr
  46.             ptr.to_i
  47.           elsif val.is_a?(DL::CPtr)
  48.             val.to_i
  49.           else
  50.             val
  51.           end
  52.         else
  53.           val
  54.         end
  55.       end
  56.       @cfunc.call(converted)
  57.     end
  58.   end

  59.   Pointer = DL::CPtr

  60.   #========== 签名解析器=========================
  61.   module CParser
  62.    
  63.     def self.parse_signature(signature, tymap = nil)
  64.       tymap ||= {}
  65.       signature = signature.gsub(/\s+/, " ").strip
  66.       case signature
  67.       when /^([\w@\*\s]+)\(([\w\*\s\,\[\]]*)\)$/
  68.         ret_part = $1
  69.         args_part = $2.strip
  70.         ret_tokens = ret_part.split(/\s+/)
  71.         args_list = args_part.split(/\s*,\s*/)
  72.         func_name = ret_tokens.pop
  73.         if func_name =~ /^\*/
  74.           func_name.gsub!(/^\*+/, "")
  75.           ret_tokens.push("*")
  76.         end
  77.         ret_type = join_types(ret_tokens)
  78.         [func_name, parse_ctype(ret_type, tymap), args_list.map { |a| parse_ctype(a.strip, tymap) }]
  79.       else
  80.         raise "无法解析函数原型: #{signature}"
  81.       end
  82.     end

  83.     #解析单个类型字符串
  84.     def self.parse_ctype(ty, tymap = nil)
  85.       tymap ||= {}
  86.       case ty
  87.       when Array
  88.         [parse_ctype(ty[0], tymap), ty[1]]
  89.       when "void"
  90.         TYPE_VOID
  91.       when "char"
  92.         TYPE_CHAR
  93.       when "unsigned char"
  94.         -TYPE_CHAR
  95.       when "short"
  96.         TYPE_SHORT
  97.       when "unsigned short"
  98.         -TYPE_SHORT
  99.       when "int"
  100.         TYPE_INT
  101.       when "unsigned int", "uint"
  102.         -TYPE_INT
  103.       when "long"
  104.         TYPE_LONG
  105.       when "unsigned long"
  106.         -TYPE_LONG
  107.       when "long long"
  108.         if defined?(TYPE_LONG_LONG)
  109.           TYPE_LONG_LONG
  110.         else
  111.           raise "不支持 long long 类型"
  112.         end
  113.       when "unsigned long long"
  114.         if defined?(TYPE_LONG_LONG)
  115.           -TYPE_LONG_LONG
  116.         else
  117.           raise "不支持 unsigned long long 类型"
  118.         end
  119.       when "float"
  120.         TYPE_FLOAT
  121.       when "double"
  122.         TYPE_DOUBLE
  123.       when /\*/, /\[\s*\]/
  124.         TYPE_VOIDP
  125.       else
  126.         if tymap[ty]
  127.           parse_ctype(tymap[ty], tymap)
  128.         else
  129.           raise "未知类型: #{ty}"
  130.         end
  131.       end
  132.     end

  133.    
  134.     def self.join_types(tokens)
  135.       tokens.join(" ")
  136.     end
  137.   end

  138.   class Handle
  139.     def initialize(lib)
  140.       @handle = DL.dlopen(lib)
  141.     end

  142.     def [](func)
  143.       @handle[func]
  144.     end

  145.    
  146.     def extern(signature, call_type = DEFAULT)
  147.       func_name, ret_type, arg_types = CParser.parse_signature(signature)
  148.       ptr = self[func_name]
  149.       if ptr.nil? || ptr == 0
  150.         raise "找不到函数: #{func_name}"
  151.       end
  152.       Function.new(ptr, arg_types, ret_type, call_type)
  153.     end
  154.   end
  155. end

  156. #===============================================================
  157. # 实际上是DL伪装Fiddle而已。
  158. #===============================================================
  159. user32 = Fiddle::Handle.new('user32')
  160. msgbox_ptr = user32['MessageBoxW']
  161. msgbox = Fiddle::Function.new(msgbox_ptr,
  162.   [Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG],
  163.   Fiddle::TYPE_LONG)  #使用 DEFAULT (stdcall)

  164. msgbox.call(0, "我自由了!", "FFI", 0)

  165. #===============================================================
  166. user32 = Fiddle::Handle.new('user32')
  167. msgbox = user32.extern('int MessageBoxW(long, void*, void*, long)')

  168. msgbox.call(0, "我再也不用win32api了!", "FFI", 0)


复制代码

Lv3.寻梦者

梦石
0
星屑
1046
在线时间
166 小时
注册时间
2025-5-6
帖子
22
2
 楼主| 发表于 2026-4-26 00:11:44 | 只看该作者
其实是把DL当作Fiddle来用
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2026-6-4 21:31

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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