数组传递给dll
离第一次接触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 = -1 Then
SetError(1)
Return -1
Else
Return $vDllAns
EndIf
EndFunc ;==>_CommSendByteArray
一般情况我只能用dllstruct*系列函数 将数组转换为自定义类型 并获取指针传入.
而他这里,数组竟然可以作为参数传入 $pAddr.
在C 中数组名就是数组的首地址, au3 的数组可以混合各种类型的变量,元素宽度都可以不统一.而 au3 明显不会这样,用指针操作就要乱套了.
百思不得其解.
猜测是 dll 内部有对 $pAddr 进一步处理.
至少我在别的地方如此调用是行不通的.
大佬路过请不吝赐教,谢谢!
我估计你是被这个函数的名字忽悠了。
我估计这个函数的目的就是发送一个数组,他需要的参数是一个指针。
而不是将AU3的数组变量直接发出去。 并没看到直接传入了一个数组。变量名 $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
目测二楼的示例代码就是正确的用法。dllcall的写法有很多种,只要理解透了,怎么写都行。p版的dllcall精讲,你值得拥有。
本帖最后由 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/
---
换个语言写就没这些麻烦事了.:face (17): ...
在这里谢谢 2,4楼的朋友.
已经好多年没有来这个论坛了,
都是 隔壁多个论坛的熟面孔, 世界真小. 发现 au3 的字符串 是指针方式传递的.
如:
Local $vDllAns = DllCall($hDll, 'int', 'SendByteArray', 'str', "0123456789abcdef", 'int', 16, 'int', 50 )
这样是可以工作的.不过,没啥用.
在C语言中用指针就能解决 ,到au3 中用 BinarytoString 遇到\0就会切断.
junyee 发表于 2021-3-12 17:49
发现 au3 的字符串 是指针方式传递的.
如:
在C中遇到0不一样结束么?字符串都是以指针传送。AU3内部封装了au3特有的STR类型而已。 本帖最后由 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 就不行了..
junyee 发表于 2021-3-12 18:51
是的.
我没有说这有不妥.
但是正常的字符串转为二进制,怎么会出现00呢? haijie1223 发表于 2021-3-12 19:02
但是正常的字符串转为二进制,怎么会出现00呢?
看来您是不常接触串口调试.
我用AU3 写上位机, 用来与 单片机之类的通讯.
通讯的数据不是字符串.
我用字符串是可以方便绕过一堆的 dllstruct 操作.
junyee 发表于 2021-3-12 19:06
看来您是不常接触串口调试.
我用AU3 写上位机, 用来与 单片机之类的通讯.
硬件数据是有可能的。
正打算研究一下串口数据的协议,QQ好友聊一波252951233 本帖最后由 junyee 于 2021-3-12 19:53 编辑
haijie1223 发表于 2021-3-12 19:09
硬件数据是有可能的。
正打算研究一下串口数据的协议,QQ好友聊一波252951233
已加.
---
我把 pcomm 常用的API都用au3封装了下.,初步测试成功.
经测试这个 PCOMM.DLL 比 commg.dll 要好用很多. moxa 官方提供了详细的开发文档.
junyee 发表于 2021-3-12 18:51
是的.
我没有说这有不妥.
STR 是字符串类型,一般字符串类型可以忽略长度参数。因为字符串的结束符就是00
你想传入00进去,那怎么可能呢。 本帖最后由 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 ="hello,world!";
test(str);
str=0;
test(str);
return 0;
}
页:
[1]
2