找回密码
 加入
搜索
查看: 6086|回复: 17

[AU3基础] 数组传递给dll

[复制链接]
发表于 2021-3-12 09:08:19 | 显示全部楼层 |阅读模式

    离第一次接触AU3一晃近15年了. 虽然学了不下十来种语言,但写点小东西还是这个最顺手.

    AU3 是一种弱变量语言, 用起来很方便, 玩得深后就会有困扰.
    由于并不是开源软件,碰到问题也只能凭脑洞瞎分析.

    AU3和很多高级语言/脚本一样,不带指针功能.  但C的指针用起来却是很爽.
   自带的ptr 函数至今不知道有何具体实用意义?

   在调用winapi或其它dll,便经常要碰到指针参数.

   这几天读了"CommMG.au3" 发现一个有趣的函数.
Func _CommSendByteArray($pAddr, $iNum, $iWait)
    If Not $fPortOpen Then
        SetError(1)
        Return 0
    EndIf

    Local $vDllAns = DllCall($hDll, 'int', 'SendByteArray', 'ptr', $pAddr, 'int', $iNum, 'int', $iWait)
    If @error <> 0 Or $vDllAns[0] = -1 Then
        SetError(1)
        Return -1
    Else
        Return $vDllAns[0]
    EndIf

EndFunc   ;==>_CommSendByteArray

一般情况我只能用  dllstruct*系列函数 将数组转换为自定义类型 并获取指针传入.
而他这里,数组竟然可以作为参数传入 $pAddr.
在C 中数组名就是数组的首地址, au3 的数组可以混合各种类型的变量,元素宽度都可以不统一.而 au3 明显不会这样,用指针操作就要乱套了.

百思不得其解.
猜测是 dll 内部有对 $pAddr 进一步处理.
至少我在别的地方如此调用是行不通的.

大佬路过请不吝赐教,谢谢!



发表于 2021-3-12 10:15:16 | 显示全部楼层
我估计你是被这个函数的名字忽悠了。
我估计这个函数的目的就是发送一个数组,他需要的参数是一个指针。
而不是将AU3的数组变量直接发出去。
发表于 2021-3-12 10:05:57 | 显示全部楼层
并没看到直接传入了一个数组。变量名 $pAddr,一般按照命名规则,可以判断他是个指针。

然后找到列子:
Func _ReadFreq()
$bBinData = Binary("0xFEFE94E003FD")    ; code to request frequency
$iNumbytes = BinaryLen($bBinData)
$tBinData = DllStructCreate("byte["&$iNumbytes&"]")
DllStructSetData($tBinData, 1, $bBinData)
$iRet = _CommSendByteArray(DllStructGetPtr($tBinData),$iNumbytes,1)   ;这里传入的是一个指针。。
If @error Or $iRet = -1 Then ConsoleWrite("!Error: " &  @error & @CRLF)

;here goes the code to read input buffer and change to ascii
;using BinaryToString, I guess
;$sfreq var holds frequency

EndFunc

发表于 2021-3-12 11:55:12 | 显示全部楼层
目测二楼的示例代码就是正确的用法。dllcall的写法有很多种,只要理解透了,怎么写都行。p版的dllcall精讲,你值得拥有。
 楼主| 发表于 2021-3-12 17:08:56 | 显示全部楼层
本帖最后由 junyee 于 2021-3-12 17:11 编辑
haijie1223 发表于 2021-3-12 11:55
目测二楼的示例代码就是正确的用法。dllcall的写法有很多种,只要理解透了,怎么写都行。p版的dllcall精讲 ...

..
确实被这个函数名迷惑了.

翻看这个函数的起因是, commMG.dll 没有提供64位的.
就自己写个 moxa 的 pcoom.dll, 要用的函数都写好了,
就是数组转换很不爽,翻看 commMG.au3 误以为可以支持 au3数组.
大概是14年用 commMG.au3 写了个串口调试工具.
当时为了处理数组自己写了个 "__CommSendByteArray" 函数,(个人习惯自己写的函数喜欢多加个下划线)
今天重读别的代码时误认为是 commMG.au3 中的.

这个是 commMG.au3 的作者帖子.
https://www.autoitscript.com/for ... -port-com-port-udf/


---

换个语言写就没这些麻烦事了. ...
 楼主| 发表于 2021-3-12 17:14:43 | 显示全部楼层
在这里谢谢 2,4楼的朋友.

已经好多年没有来这个论坛了,
都是 隔壁多个论坛的熟面孔, 世界真小.
 楼主| 发表于 2021-3-12 17:49:24 | 显示全部楼层
发现 au3 的字符串 是指针方式传递的.

如:
Local $vDllAns = DllCall($hDll, 'int', 'SendByteArray', 'str', "0123456789abcdef", 'int', 16, 'int', 50 )

这样是可以工作的.不过,没啥用.
在C语言中用指针就能解决 ,到au3 中用 BinarytoString 遇到\0就会切断.


发表于 2021-3-12 18:34:47 | 显示全部楼层
junyee 发表于 2021-3-12 17:49
发现 au3 的字符串 是指针方式传递的.

如:

在C中遇到0不一样结束么?字符串都是以指针传送。AU3内部封装了au3特有的STR类型而已。
 楼主| 发表于 2021-3-12 18:51:22 | 显示全部楼层
本帖最后由 junyee 于 2021-3-12 19:00 编辑
haijie1223 发表于 2021-3-12 18:34
在C中遇到0不一样结束么?字符串都是以指针传送。AU3内部封装了au3特有的STR类型而已。

是的.
我没有说这有不妥.

似乎au3的字符串传递的就是指针,如果想把 变量,如 binaray("0x303132330035363738") 转为字符串传递给  dllcall  就会遇到截断的问题.
打个比方,三楼提供的代码可以简化写为:
Local $vDllAns = DllCall($hDll, 'int', 'SendByteArray', 'str', BinaryToString("0xFEFE94E003FD"), 'int', 6, 'int', 10 )

但是,如果数据中有 00 就不行了..







发表于 2021-3-12 19:02:45 | 显示全部楼层
junyee 发表于 2021-3-12 18:51
是的.
我没有说这有不妥.

但是正常的字符串转为二进制,怎么会出现00呢?
 楼主| 发表于 2021-3-12 19:06:00 | 显示全部楼层
haijie1223 发表于 2021-3-12 19:02
但是正常的字符串转为二进制,怎么会出现00呢?

看来您是不常接触串口调试.

我用AU3 写上位机, 用来与 单片机之类的通讯.
通讯的数据不是字符串.

我用字符串是可以方便绕过一堆的 dllstruct 操作.
发表于 2021-3-12 19:09:02 | 显示全部楼层
junyee 发表于 2021-3-12 19:06
看来您是不常接触串口调试.

我用AU3 写上位机, 用来与 单片机之类的通讯.

硬件数据是有可能的。
正打算研究一下串口数据的协议,QQ好友聊一波252951233
 楼主| 发表于 2021-3-12 19:52:23 | 显示全部楼层
本帖最后由 junyee 于 2021-3-12 19:53 编辑
haijie1223 发表于 2021-3-12 19:09
硬件数据是有可能的。
正打算研究一下串口数据的协议,QQ好友聊一波252951233

已加.

---
我把 pcomm 常用的API都用au3封装了下.,初步测试成功.
经测试这个 PCOMM.DLL 比 commg.dll 要好用很多. moxa 官方提供了详细的开发文档.




发表于 2021-3-13 00:00:24 | 显示全部楼层
junyee 发表于 2021-3-12 18:51
是的.
我没有说这有不妥.

STR 是字符串类型,一般字符串类型可以忽略长度参数。因为字符串的结束符就是00
你想传入00进去,那怎么可能呢。
 楼主| 发表于 2021-3-13 08:51:16 | 显示全部楼层
本帖最后由 junyee 于 2021-3-13 08:54 编辑
gyp2000 发表于 2021-3-13 00:00
STR 是字符串类型,一般字符串类型可以忽略长度参数。因为字符串的结束符就是00
你想传入00进去,那怎么 ...

你没理解我的意思..

AU3 没有指针,但str类型是以指针的方式传递.
我想用 Binary 转为 string 变通实现指针传递.


可以工作.
Local $vDllAns = DllCall($hDll, 'int', 'SendByteArray', 'str', BinaryToString("0xFEFE94E003FD"), 'int', 6, 'int', 10 )

这个就不行
Local $vDllAns = DllCall($hDll, 'int', 'SendByteArray', 'str', BinaryToString("0xFE0094E003FD"), 'int', 6, 'int', 10 )

在传递时时字符串被破坏.或者说是new 了一个变量.我讨论不是AU3 这种处理方式是否不妥(事实上是很妥当的,向不明函数传递一个指针是很危险的),
而是我这个变通的方法在此行不通.

用C写个示例你就明白了.

#include "stdio.h"


void test(char* str)
{
        int i;
        printf("\n%s\n",str);
        for (i=0;i<12;i++){
                printf("%02x ", *(str++));
        }
}

int main(int args, char* argc[])
{
        char str[16] ="hello,world!";

        test(str);
        
        str[4]=0;
        test(str);
        return 0;
}












本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-3-29 03:31 , Processed in 0.079670 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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