查看: 2751|回复: 2

[已经解决] 利用Win32API.new()命令调用DLL时,怎么返回文本?

[复制链接]
梦石
0
星屑
3242
在线时间
205 小时
注册时间
2019-9-16
回帖
195
发表于 2019-10-26 17:14:03 | 显示全部楼层 |阅读模式

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

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

×
Win32API.new("dll", "_ceshi", ['i','i'], 'i')

上面i代表int,也就是整数型变量,这个我知道。但是怎么返回文本型变量呢?
梦石
0
星屑
9862
在线时间
580 小时
注册时间
2017-9-28
回帖
203
发表于 2019-10-26 18:37:15 | 显示全部楼层
一般 api 会设计成传入一个由用户申请的空间,api 负责往里面填东西,比如,

假设是用 C 写的 dll,写一个 f 函数功能是填充 *:
  1. void f(char *buf, int size) { for (int i = 0; i < size; ++i) buf[i] = '*'; }
复制代码
那么 ruby 调用时:
  1. Win32API.new('a.dll', 'f', 'pl', 'v').call(buf = "\0" * 42, 42)
复制代码

当然,有的时候确实是 api 自己申请的字符串空间并返回地址(ruby 里会取到一个整数),这时候就要小心一点,
首先用 memcpy 或者 RtlMoveMemory 把 C 字符串从这个地址拿到 ruby 的一个字符串里,
然后记得自己 free 或者 api 提供 free 操作来释放空间
给一个参考实现:
  1. def ptr2str pointer
  2.   assert!(Integer === pointer)
  3.   len = api('kernel32', 'lstrlen').call pointer
  4.   return '' if len.zero?
  5.   str = [].pack("x#{len}")
  6.   api('kernel32', 'RtlMoveMemory').call str, pointer, len
  7.   str
  8. end
复制代码

点评

汗!原来这么复杂,我要消耗消化,先谢谢了。另外,我调用的时候确实返回的是疑似地址的整数  发表于 2019-10-26 18:56

评分

参与人数 1星屑 +50 赞 +1 收起 理由
guoxiaomi + 50 + 1 精品文章

查看全部评分

喵喵喵
回复 1 0

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部