Hi all, I have some code like this-
type
A* = ref object of RootObj
#properties ...
B* = ref object of A
# properties ...
FuncPtr* = proc(x : int, y : A) # A function pointer aka delegate
Person* = ref object
fnPtrList* : seq[FuncPtr] # this list will init later
# props ...
proc setFuncPtr(me : Person, pfnPtr : FuncPtr) = # this proc will fetch the list
me.fnPtrList.add(pfnPtr)
Now, i want to create the person object
proc sampleProc(p : int, q : B) # Here i am using B instead of A. Because i need it
var p = new Person
p.setFuncPtr(sampleProc) # This line is showing error. Compiler says it is expecting type "A" instead of B.
I experienced this myself, unfortunately there's no "good" solution to this. Still I can think of three way to workaround this:
1. the easiest way change the function:
proc sampleProc(p : int, q : A) =
let q = B(q)
2. wrap the function inside a closure
p.setFuncPtr(proc(p: int, q: A) = sampleProc(q, B(q))
This can also also be relegated to the register proc:
proc setFuncPtr[T: A](me : Person, pfnPtr: proc(y: int, q: T)) = # this proc will fetch the list
me.fnPtrList.add(proc(x: int, y: A) = pfnPtr(x, T(y)))
3. This is EventData
type
EventData* = ref object
msg * : UINT # this represent the window message
fnPtr* : FuncPtr # This is what i wrote in my above comment.
isProcSet : bool # A boolean flag
Next, there so many types to use inside the function pointer. Here is a list
type
EventArgs* = ref object of RootObj
MouseEventArgs* = ref object of EventArgs
KeyEventArgs* = ref object of EventArgs
PaintEventArgs* = ref object of EventArgs
#... And lot more
Next, populating the event data list for Form object
proc addHandler(me : Form, evt : UINT, pfn : FuncPtr ) =
var ed : EventData = new EventData
ed.msg = evt # messages like WM_PAINT etc
ed.fnPtr = pfn
ed.isProcSet = true
me.eventDataList.add(ed) # we put the event data to list
Next, this is happening inside my wndProc function
case message
of WM_PAINT :
thisForm = getTheCurrentForm(hwnd) # this will get the current Form object
evtData = thisForm.getEventData(message) # this will get the event handler for current message
if evtData.isProcSet :
var pea : PaintEventArgs = newPaintEventArgs(wp, lp) # We create a paint event args
procCall(evtData.fnPtr(thisForm, pea)) # this is our event handling
of WM_LBUTTONDOWN :
# same process for left button down
So this is the total process. I am clueless now.