这是尝试引入 AHK v2回调创建 到 AHK v1 的功能。在 AHK v2 中,注册回调被替换为回调创建。
让v1能实现v2的CallbackCreate函数功能
具体说明:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=53457
代码示例:
#NoEnv
#SingleInstance force
; https://github.com/HelgeffegleH/AHK-misc./blob/master/functions/callbackcreate/callbackcreate.ahk
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=53457
; 这是尝试引入 AHK v2回调创建 到 AHK v1 的功能。在 AHK v2 中,注册回调被替换为回调创建。
; 官方示例1
callback := CallbackCreate("TheFunc", "F&", 3) ; 必须为 32 位指定参数列表大小。
DllCall(callback, float, 10.5, int64, 42)
TheFunc(params) {
MsgBox % NumGet(params+0, "float") ", " NumGet(params+A_PtrSize, "int64")
}
; 官方示例2
i := new myClass("Apple")
callbackFunc := objbindmethod(i, "myMethod", "BoundParam1")
address := CallbackCreate(callbackFunc,, 1)
dllcall(address, "int", 37)
callbackfree(address)
return
class myClass {
__new(name){
this.name := name
}
myMethod(arg1, arg2){
msgbox % this.name "`n" arg1 "`n" arg2
}
}
return
CallbackCreate(Function , Options := "", ParamCount := ""){
; Address := CallbackCreate(Function , Options := "", ParamCount := Function.MinParams)
; see: https://lexikos.github.io/v2/docs/commands/CallbackCreate.htm
; Note that the v2 version doesn't affect A_EventInfo, this version does.
/*
This function fails when:
Function is not an object or a valid function name.
Function has a MinParams property which exceeds the number of parameters that the callback will supply.
ParamCount is negative.
ParamCount is omitted and: 1) Function has no MinParams property; or 2) the & option is used with the standard 32-bit calling convention.
*/
local
; Input validation start. This is partly 'ported' from BIF_CallbackCreate (a097)
if (!io := isobject(Function)) && !isfunc(Function)
throw exception("Parameter #1 invalid.", -1)
fn := "" ; If a function name was passed, retrieve the function reference below.
minparams := ( io ? Function : fn := func(Function) ).MinParams
if (minparams != "")
if minparams is not number ; if the MinParams property doesn't return a number, minparams is 0.
minparams := 0
has_minparams := minparams != "" ? true : false
minparams := has_minparams ? minparams : 0
use_cdecl := instr(options, "C")
require_param_count := a_ptrsize == 4 && !use_cdecl
pass_params_pointer := instr(options, "&", true)
if (ParamCount != "") {
actual_param_count := ParamCount
if ( actual_param_count < 0 || ( has_minparams && (pass_params_pointer ? 1 : actual_param_count) < minparams ) )
throw exception("Parameter #3 invalid.", -1)
} else if (!has_minparams || (pass_params_pointer && require_param_count)) {
throw exception("Parameter #3 must not be blank in this case.", -1)
} else {
actual_param_count := minparams
}
if (a_ptrsize == 4 && (!use_cdecl && actual_param_count > 31) )
throw exception("Parameter #3 invalid.", -1)
; Input validation end.
Function := io ? Function : fn ; Make sure Function is a function reference and not just a name, avoids finding the reference on each callback.
cbo := { actual_param_count : actual_param_count ; Callback object, its address is passed to the callback router vi a_eventinfo
, pass_params_pointer : pass_params_pointer
, Function : Function }
if (fn && !pass_params_pointer && !fn.isvariadic) {
; Meaning the name of a non variadic function was passed as Function, and not using the '&' option.
; No need to route the callback.
cb := registercallback(fn.name, options, actual_param_count)
} else {
; A Function object or name of a variadic function or '&' option was passed. Needs to route the callback
static router_fn := "__callbackcreate_router__"
cb := registercallback(router_fn, options, actual_param_count, &cbo)
}
if !cb ; Hopefully, this shouldn't happen
throw exception("registercallback failed")
objaddref( &cbo ) ; This is decremented in CallbackFree when freeing the callback.
CallbackFree(cbo, cb) ; Add to cache.
return cb ; Return the callback address
}
CallbackFree(Address, cb := "") {
; Address, the address to free.
; cb, internal use, always omit. Used for setting/getting callback functions
; see: https://lexikos.github.io/v2/docs/commands/CallbackCreate.htm
static callback_cache := [] ; Contains all callback objects.
if cb { ; add to cache
if isobject(Address)
return callback_cache[ cb ] := Address
throw exception("?")
}
if address is not number
address := 0
if (address < 65536 && address >= 0)
throw exception("Parameter #1 invalid.", -1)
; Free the address and callback object.
dllcall("GlobalFree", "Ptr", Address, "Ptr")
objrelease( &callback_cache.delete( Address ) )
return
}
__callbackcreate_router__(p*) {
; Help function.
; Routes all callbacks.
; Since this function is variadic, all parameters are passed by address.
static p_type := a_ptrsize == 4 ? "uint" : "int64"
local
cbo := object( a_eventinfo ) ; a_eventinfo contains the address of the callback object.
if !cbo.pass_params_pointer { ; The '&' option was not used, fetch all parameters and pass directly to the script callback.
args := []
loop % cbo.actual_param_count
args.push( numget(p+0, a_ptrsize * (a_index-1), p_type) )
} else { ; using the "&" option, just pass the pointer to the arguments to the script callback.
args := [p]
}
return cbo.function.call( args* ) ; Call script callback
}
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。

评论(0)