仅作参考

#NoEnv
#SingleInstance force

; #Include %A_ScriptDir%\callbackcreate.ahk ; https://github.com/HelgeffegleH/AHK-misc./blob/master/functions/callbackcreate/callbackcreate.ahk

; 官方示例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
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。