Results 1 to 10 of 10

Thread: Another huge game changer feature: Delegate function pointer types (Call by pointer)

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    Lightbulb Another huge game changer feature: Delegate function pointer types (Call by pointer)

    Thought this feature was also worth flagging for those who don't follow tB GitHub or Discord.

    twinBASIC now supports Call By Pointer, by way of Delegates, which are function pointer types.

    Code:
        Private Delegate Function Delegate1 (ByVal A As Long, ByVal B As Long) As Long
        
        Private Sub Command1_Click()
            Dim myDelegate As Delegate1 = AddressOf Addition
            MsgBox "Answer: " & myDelegate(5, 6)
        End Sub
        
        Public Function Addition(ByVal A As Long, ByVal B As Long) As Long
            Return A + B
        End Function
    You can of course also use a LongPtr variable to assign to the delegate type.

    The delegate type can also be used in interface/API declarations and as members of a User-defined type, for example, the ChooseColor API:
    Code:
    Public Delegate Function CCHookProc (ByVal hwnd As LongPtr, ByVal uMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Public Type CHOOSECOLOR
        lStructSize As Long
        hwndOwner As LongPtr
        hInstance As LongPtr
        rgbResult As Long
        lpCustColors As LongPtr
        Flags As ChooseColorFlags
        lCustData As LongPtr
        lpfnHook As CCHookProc 'Delegate function pointer type instead of LongPtr
        lpTemplateName As LongPtr
    End Type
    If you already have code assigning a Long/LongPtr to the lpfnHook member, it will continue to work normally, but now you can also have the type safety benefits of setting it to a method matching the Delegate:
    Code:
    Dim tCC As CHOOSECOLOR
    tCC.lpfnHook = AddressOf ChooseColorHookProc
    
    ...
    
    Public Function ChooseColorHookProc(ByVal hwnd As LongPtr, ByVal uMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    
    End Function
    A much, much better way of implementing call by pointer compared to the standard ways of DispCallFunc or asm thunks!

  2. #2
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    That is a massive step for a VB6 clone! Huge.

    How close are you guys to being able to write things like this in tB?
    Code:
    Public Class Form1
    
        Private Delegate Function FilterPredicate(Of T)(ByVal item As T)
        Private Function Filter(Of T)(ByVal items As T(), ByVal filterPred As FilterPredicate(Of T)) As T()
            Dim newList As New List(Of T)
    
            For Each item In items
                If filterPred(item) Then newList.Add(item)
            Next
            Return newList.ToArray()
        End Function
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Dim names = {"John", "Smith", "Kane", "Tessa", "Yoland", "Royce", "Samuel"}
    
            'Filter out names that start with "s"
            Dim filterNames = Filter(names, Function(n) n.ToLower.StartsWith("s"))
            Stop
    
        End Sub
    
    End Class
    
    I'm referring specifically to the Filter function and everything that supports it like generic functions, anonymous functions and of course delegates which you already have.
    Last edited by Niya; May 22nd, 2025 at 09:27 PM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    tB has some support for generics in sub/function and classes, but doesn't support them with delegates yet. Or whatever the heck that 2nd argument at the Filter callsite.

    I started seeing how close I could get and I'll come back to it later, for now here's some generics examples working right now.

    Code:
    Module testmod
            Private Sub testc()
    
                Dim names As List(Of String) = New List(Of String)(Array("John", "Smith", "Kane", "Tessa", "Yoland", "Royce", "Samuel"))
                Dim s As String = names(0)
                Debug.Print s
            End Sub
    End Module
    [COMCreatable(False)]
    Class List(Of T)
        Private src() As T
        Private c As Long
        Sub New(p() As T)
            For i As Long = 0 To UBound(p)
                ReDim Preserve src(c)
                src(c) = p(i)
                c += 1
            Next
        End Sub
        [DefaultMember]
        Function GetAt(ByVal idx As Long) As T
            Return src(idx)
        End Function
        Public Property Get Count() As Long
            Return c
        End Property
    End Class
    Code:
        Public Function GetMem(Of T)(ByVal ptr As LongPtr) As T
            vbaCopyBytes(LenB(Of T), VarPtr(GetMem), ptr)
        End Function
        Public Function DCast(Of T, T2)(ByVal v As T2) As T
            If LenB(Of T2) >= LenB(Of T) Then
                vbaCopyBytes(LenB(Of T), VarPtr(DCast), VarPtr(v))
            Else
                vbaCopyBytes(LenB(Of T2), VarPtr(DCast), VarPtr(v))
            End If
        End Function
    Last edited by fafalone; May 23rd, 2025 at 12:33 AM.

  4. #4
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    Wow. tB has come a long way.

    Quote Originally Posted by fafalone View Post
    Or whatever the heck that 2nd argument at the Filter callsite.
    You referring to this?
    Code:
    Dim filterNames = Filter(names, Function(n) n.ToLower.StartsWith("s"))
    You guys probably don't have that yet in tB. Filter is what is called a higher order function. It takes a function as a parameter, delegates are kind of a prerequisite for them, at least in manner presented here. The second parameter defines what is called an anonymous function. In this case, Filter cycles through the items from the array passed into the first parameter and calls that anonymous function on each of them to determine whether they start with "s" or not.

    The idea here is that you can define a single filtering function that can have wildly different filtering conditions defined at the callsite. Delegates are what make this possible in .Net.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  5. #5
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    3,560

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    This is very good. Hopefully examples like these can make their way into the documentation for TB (if not already present)

    The idea of delegates as described above is very informative for many of us that haven't used them before. An example as to why we would want to use them is also very useful. More of those required.

    Niya's example is also useful demonstrating the use of a delegate upon which the anonymous function performs its wizardry. I have used anonymous functions before in TypeScript and they are compact and I don't want to say the word again but, useful.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    The New Features wiki page already had examples for delegates and generics; I added the Class generic example when I wrote it yesterday.

  7. #7
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    3,560

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    Superb!
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  8. #8
    Fanatic Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    760

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    Having a background only in VB, I'm not clear on what Delegates or they're usefulness. Anyone care to enlighten me? When would I need this?

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    It's primarily for when you only have a pointer to a function and want to call that function. As an example, in an Excel XLL addin, the only practical way to find the function your addin has to call it to use GetProcAddress(GetModuleHandleW(0), "MdCallback12")-- there's no separate DLL for a regular declare. That just gives you an address, so how do you call it? In VB6, you need to use a big, painful, and slow DispCallFunc routine or inline assembly. In tB,

    Code:
    Private Const EXCEL12ENTRYPT = "MdCallBack12"
    Private Delegate Function EXCEL12PROC (ByVal xlfn As ExcelCommandNumbers, ByVal coper As Long, rgpxloper12 As LongPtr, xloper12Res As XLOPER12) As Long
    Private pexcel12 As EXCEL12PROC
    
    pexcel12 = CType(Of EXCEL12PROC)(GetProcAddress(GetModuleHandleW(0), EXCEL12ENTRYPT))
    Now pexcel12 is used like any other function... Dim result As Long = pexcel12(123, 4, ...) . The arguments will come up in Intellisense.


    The other use is type safety in callbacks. For APIs that use callback functions, typing it as a delegate tells you what the definition should look like and makes sure it matches up. I.e. for a TimerProc for SetTimer, with delegates it's not just some random LongPtr you have to look to outside docs to see how it's set up with no help from the compiler,

    Code:
    Public Delegate Sub TIMERPROC (ByVal hWnd As LongPtr, ByVal uMsg As Long, ByVal TimerID As LongPtr, ByVal Tick As Long)
    Public Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As TIMERPROC) As LongPtr
        Sub test()
            SetTimer 0, 0, 0, AddressOf BadProc
        End Sub
        Function BadProc(OnlyOne As Long) As Byte
            
        End Function
        Sub GoodProc(ByVal hWnd As LongPtr, ByVal uMsg As Long, ByVal TimerID As LongPtr, ByVal Tick As Long)
            
        End Sub
    You'll see here you get a warning that it's mismatched. Changing it to GoodProc, the warning goes away.

    (Note: WinDevLib currently doesn't use delegates in API defs due to a bug relating to delegates in packages, but you could do Dim lpProc As TIMERPROC = AddressOf BadProc/GoodProc): SetTimer 0, 0, 0, lpProc
    Last edited by fafalone; May 28th, 2025 at 05:44 AM.

  10. #10
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Another huge game changer feature: Delegate function pointer types (Call by point

    Quote Originally Posted by AAraya View Post
    Having a background only in VB, I'm not clear on what Delegates or they're usefulness. Anyone care to enlighten me? When would I need this?
    In addition to what faf said, here's a simple way to conceptualize it. It's a "type safe function pointer".
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width