私人定制开发服务,请加我微信 sunwind1576157。
AutoHotkey调用dll都是高级人的应用,数组、结构体、指针、指针数组的传参真挺难。
一直对numput 、numget心生敬畏,终于花了1个月啃了这块骨头。
不说了,赶紧上车,无图无真相!
查询【000001】【000012】【600050】3只股票的5档行情
#NoEnv
;sunwind
;2019年6月8日
;功能:调用TradeX.dll获取五档行情
;感谢:ThinkAI、彪悍的小玄、爱尔兰之狐 的帮助。
;运行环境:兼容AutoHotkey A32 U32
;操作系统:Windows10 64位
dll:=A_ScriptDir . "\TradeX.dll"
Global g_dllName:="TradeX"
Global g_pszResult , g_pszErrInfo , g_nShortCount
/*
g_pszResult - 此 API 执行返回后,Result内保存了返回的查询数据, 形式为表格数据, 行数据之间通过\n 字符分割,列数据之间通过\t 分隔。 一般要分配 1024*1024 字节的空间。出错时为空字符串
*/
VarSetCapacity(g_pszResult, 1048576)
/*g_pszErrInfo - 此 API 执行返回后,如果出错,保存了错误信息说明。一般要分配 256 字节的空间。没出错时为空字符串。
*/
VarSetCapacity(g_pszErrInfo, 256) ;256字节
VarSetCapacity(g_nShortCount, 4) ;4字节
caption := "加载DLL"
;当需要重复调用一个 DLL 时, 预先明确装载它可以显著提高执行效率
hModule:=DllCall("LoadLibrary", "str",dll, "Ptr")
caption := "连接普通行情服务器"
host:="59.173.18.140",port:=7709
;~ host:="119.147.212.81",port:=7709
; 1 : 招商证券深圳行情 119.147.212.81:7709
; 2 : 华泰证券(南京电信) 221.231.141.60:7709
; 3 : 华泰证券(上海电信) 101.227.73.20:7709
; 4 : 华泰证券(上海电信二) 101.227.77.254:7709
; 5 : 华泰证券(深圳电信) 14.215.128.18:7709
; 6 : 华泰证券(武汉电信) 59.173.18.140:7709
; 7 : 华泰证券(天津联通) 60.28.23.80:7709
; 8 : 华泰证券(沈阳联通) 218.60.29.136:7709
; 9 : 华泰证券(南京联通) 122.192.35.44:7709
; 10 : 华泰证券(南京联通) 122.192.35.44:7709
aResult:=DllCall("TradeX\TdxHq_Connect", "Astr",host,"Short",port,"str",g_pszResult,"str",g_pszErrInfo,"int")
if(ErrorLevel=-2)
m(0, caption, "TdxHq_Connect" . "`r`n" . "返回值类型或某个指定的参数类型无效. ")
;~ if(ErrorLevel=0)
;~ m(0, caption, "TdxHq_Disconnect" "`r`n" "开始测试")
a:=StrGet(&g_pszResult, "cp0")
b:=StrGet(&g_pszErrInfo, "cp0")
m(0, caption,a "`r`n" b "`r`n")
caption := "获取5档行情"
xMarket:= [0,0,1]
arr:=["000001","000012","600050"]
Count:=arr.MaxIndex()
NumPut(Count,&g_nShortCount,,"Char")
VarSetCapacity(zqdmStr,Count*14)
VarSetCapacity(zqdmPtr,Count* A_PtrSize)
arrPushStruct(arr,zqdmStr,zqdmPtr)
ret := DllCall("TradeX\TdxHq_GetSecurityQuotes", "ptr", &xMarket, "ptr", &zqdmPtr, "ptr",&g_nShortCount, "str", g_pszResult, "str", g_pszErrInfo)
a:=StrGet(&g_pszResult, "cp0")
b:=StrGet(&g_pszErrInfo, "cp0")
m(0, caption,a "`r`n" b "`r`n")
caption:= "断开连接"
aResult:=DllCall("TradeX\TdxHq_Disconnect")
if(ErrorLevel=-2)
m(0, caption, "TdxHq_Disconnect" "`r`n" "返回值类型或某个指定的参数类型无效. ")
if(ErrorLevel=0)
m(0, caption, "TdxHq_Disconnect" "`r`n" "结束测试")
DllCall("FreeLibrary", "Ptr", hModule) ; 为了释放内存, 在使用 DLL 后需要进行卸载.
return
;功能:把数组元素的地址转存到一个结构体中。
;困难:
;1.要适配的dll只会按cp0解析地址,如果用AutoHotkeyU32默认地址是按cp1200存储地址。
;2.用AutoHotkeyU32 利用arr.GetAddress(A_Index)获取数组地址,默认会是CP1200编码,要适配的dll无法解码
;
;解决:
;1.先把arr数组的每项zqdm转存到zqdmStr结构体中,方便自己获取地址(不用arr.GetAddress)。
;2.再将每个zqdmStr的地址 存到 zqdmPtr结构体中。
arrPushStruct(arr,ByRef zqdmStr,ByRef zqdmPtr)
{
bytes_per_char := A_IsUnicode ? 2 : 1
SizeInBytes := (StrLen(arr[1]) + 1) * bytes_per_char
Addr:=&zqdmPtr
For Each, v In arr
{
elementAdr:=(&zqdmStr)+SizeInBytes*(A_Index-1) ;遍历数组中每个元素的地址
strput(arr[A_Index],elementAdr,"cp0") ;强制以cp0转存,以适配特定dll。先把arr数组转存到zqdmStr结构体
Addr :=NumPut(elementAdr,Addr+0,"Ptr") ;NumPut会自动更新addr为下一个元素的地址
;~ 以二进制格式把数字存储到指定地址+偏移的位置.
;~ NumPut(Number, VarOrAddress [, Offset := 0][, Type := "UPtr"])
}
}
;封装msgbox为函数,默认 5秒自动关闭弹出的对话框
m(Options, Title, Text, Timeout=5)
{
MsgBox, % Options,% Title, % Text, % Timeout
}
其它语言示例
autoit3的示例:
;dim $req[2][2]
;
;$req[0][0] = 0
;$req[0][1] = "000001"
;
;$req[1][0] = 1
;$req[1][1] = "600300"
;
Func TdxHq_GetSecurityQuotes($req, ByRef $result, ByRef $errinfo)
If Not IsArray($req) Or UBound($req, 0) <> 2 Then
$errinfo = "参数错误! $req不是数组或者数组维度不是2"
Return False
EndIf
Local $row = UBound($req, 1);
Local $col = UBound($req, 2);
If $row > 80 Then
$errinfo = "单次请求股票数太多! 最大数目80"
Return False
EndIf
If $col <> 2 Then
$errinfo = "数组元素应该包含: 市场代码和股票代码"
Return False
EndIf
Local $sField = ""
For $k=0 to $row - 1
$sField &= "char[12];"
Next
Local $tagStruct = "struct;byte vecMarket[" & $row & "]; int_ptr vecZqdmPtr[" & $row & "]; " & $sField & "endstruct"
Local $tStruct = DllStructCreate($tagStruct)
If @error Then
$errinfo = @error
Return False
EndIf
For $i=0 to $row - 1
DllStructSetData($tStruct, 1, $req[$i][0], $i+1)
If @error Then
$errinfo = @error
Return False
EndIf
DllStructSetData($tStruct, 3 + $i, $req[$i][1])
If @error Then
$errinfo = @error
Return False
EndIf
DllStructSetData($tStruct, 2, DllStructGetPtr($tStruct, 3 + $i), $i+1)
If @error Then
$errinfo = @error
Return False
EndIf
Next
DllStructSetData($g_nShortCount, 1, $row)
Local $aResult = DllCall($g_dllName, "boolean", "TdxHq_GetSecurityQuotes", _
"ptr", DllStructGetPtr($tStruct, 1), _
"ptr", DllStructGetPtr($tStruct, 2), _
"ptr", DllStructGetPtr($g_nShortCount), _
"ptr", DllStructGetPtr($g_pszResult), _
"ptr", DllStructGetPtr($g_pszErrInfo))
If @error Then
$errinfo = @error
Return False
EndIf
If $aResult[0] == 0 Then
$errinfo = DllStructGetData($g_pszErrInfo, 1)
Else
$count = DllStructGetData($g_nShortCount, 1)
$result = DllStructGetData($g_pszResult, 1)
EndIf
$tStruct = 0
Return $aResult[0]
EndFunc