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

Project1

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

[已经解决] 自己做dll,return 不同类型变量怎么搞阿?

 关闭 [复制链接]

Lv1.梦旅人

梦石
0
星屑
60
在线时间
61 小时
注册时间
2006-9-15
帖子
946
跳转到指定楼层
1
发表于 2009-11-16 20:52:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 secondsen 于 2009-11-18 08:54 编辑

如题。。。

MS
int  XXX()
{
    return int XXX;
}

怎么能返回不同类型的值啊?

我这要返回几个long int 还有一个字符串怎么弄呢?

Lv1.梦旅人

神之瞳

梦石
0
星屑
60
在线时间
5 小时
注册时间
2009-7-5
帖子
314
2
发表于 2009-11-16 22:45:35 | 只看该作者

九月三日

  有时我真不理解,怎么有另一个人能够爱她,可以爱她,殊不知我爱她爱得如此真切,如此忘情,如此情意缱倦,除了她我什么也不了解,什么也不知道,什么也没有呀!
——摘自《少年维特之烦恼》

谨以 纪念一段消逝了的感情
ILY ZXY

NOIp什么的最讨厌了!

啊……讨厌,为什么我的网盘全部坏掉了……
zoomshare恢复了,虚惊一场
可恶的skydrive,我XX你的OO,竟把我的帐号封了!
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
3
发表于 2009-11-17 00:16:04 | 只看该作者
1、返回一个包含多个域的结构体:
  1. struct ret
  2. {
  3.     int i;
  4.     long l;
  5.     char *c;
  6. };

  7. ret XXX()
  8. {
  9.     ret r = { 0x7f, 0x7fff, "Hello World!" };
  10.     return r;
  11. }
复制代码
2、原地修改参数的值,达到返回值的效果(即楼上百度知道中的方法,也是大部分 API 函数的运作方式——函数需要操作和返回的都放在参数列表中,而返回值则用来表示函数成功或失败):
  1. #include <stdio.h>

  2. void XXX(int &i, long &l, char *c)
  3. {
  4.     i = 0x7f;
  5.     l = 0x7fff;
  6.     sprintf(c, "Hello World!");
  7. }


  8. int main()
  9. {
  10.     int i;
  11.     long l;
  12.     char c[13];
  13.     XXX(i, l, c);
  14.     printf("%d,%d,%s\n", i, l, c);
  15.     return 0;
  16. }
复制代码
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
60
在线时间
61 小时
注册时间
2006-9-15
帖子
946
4
 楼主| 发表于 2009-11-17 11:23:51 | 只看该作者
本帖最后由 secondsen 于 2009-11-17 11:34 编辑

结构体怎么返回给Rm呢?

另外 sprintf 长整形的 不用%ld么?我不懂C++,问问。
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
1
星屑
10283
在线时间
4442 小时
注册时间
2005-10-22
帖子
6992

开拓者贵宾

5
发表于 2009-11-17 12:25:10 | 只看该作者
结构体怎么返回给Rm呢?

另外 sprintf 长整形的 不用%ld么?我不懂C++,问问。
secondsen 发表于 2009-11-17 11:23


RM用的话返回字符串(指针)吧 囧
然后把东西都丢字符串里
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
6
发表于 2009-11-17 14:03:14 | 只看该作者
先纠正一下上面的代码,应该用 char[13] 而不是 char * 类型,否则这个结构体就成了一个多级的结构

RM 通过传递字符串就可以获取到 DLL 中的函数返回的结构体指针,但是让 DLL 函数返回一个指针有两个缺点,第一是返回局部变量的话在函数返回后数据就会丢失,一般是要返回静态存储的变量;第二是在 RM 中获取不方便~通常我们用的 Win32API 如果指定函数返回类型为 p 时,Win32API.new 会把 DLL 函数返回的指针当做一个空终止的字符串(即以 \0 结束的字符串),所以在获取到 \0 这个字节时,Win32API.new 就会终止……很明显这无法获取一个完整的结构体,因为结构体中可能有大量的 \0,而这些 \0 都是有意义的~即便把整个结构体转换为一个字符串,还是会在 \0 这个不应该终止的地方终止

所以建议你用第二种方式来达到同样的通信接口效果,非要返回一个结构体的话,可以把 Win32API.new 的返回值那里设为 "i",这样就能获取到结构体的首地址(而不是像 "p" 那样返回一个空终止的字符串),然后再通过 RtlMoveMemory 这样的函数去拷贝从这个地址开始结构体大小这么多的内存区域,如下:
DLL:
  1. struct ret
  2. {
  3.     int i;
  4.     long l;
  5.     char c[13];
  6. };

  7. _declspec(dllexport) ret *XXX()
  8. {
  9.     static ret r = { 0x7f, 0x7fff, "Hello World!" };
  10.     return &r;
  11. }
复制代码
RM:
  1. XXX = Win32API.new("GeneralDllApp", "XXX", "V", "i")
  2. MoveMemory = Win32API.new("kernel32", "RtlMoveMemory", "pii", "v")

  3. buff = " " * 24
  4. MoveMemory.call(buff, XXX.call, 24)

  5. p buff
  6. p buff.unpack("ilA*")
复制代码
至于长整形格式化字符串的类型前缀,用 ld 当然是最好的 ^^,由于我们是在 32 位平台下,所以 ld 还是 d 都无所谓了
回复 支持 反对

使用道具 举报

Lv1.梦旅人

风之塞尔达

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

贵宾

7
发表于 2009-11-17 14:57:36 | 只看该作者
本帖最后由 link006007 于 2009-11-17 15:10 编辑

简单麻烦点的话可以分别返回基本类型
这样至少可以不要考虑*24那样字节对齐的问题, 不然还要对不同版本的dll写不同版本的rb脚本(不过这种情况可以忽略不计...)
在程序里延续塞尔达的传说, 在画板上勾勒塞尔达的轮廓!!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-12-28 03:20

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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