Fog Creek Software
Discussion Board




VBA - CallBacks = Few Cents Less Than A Dollar?

How does the absence of "callbacks" pose a limitation to and cripple the usefulness of a macro-programming-language such as VBA?

I read this statement from the Wikipedia and needed some supplementary text to elaborate it. Would you please mind?

"VBA is functionally rich and extremely flexible but it does have some important limitations, most notably in its ability to handle callback functions, a fundamental requirement of a "full" Windows programming language."

http://en.wikipedia.org/wiki/Visual_Basic_for_Applications

PS: I've used callbacks with Win32 API as well as implemented my own mechanism for using callbacks by implementing interfaces in between ActiveX components and their clients, so I am not actually asking for a tutorial on callbacks.

Sathyaish Chakravarthy
Tuesday, May 11, 2004

Eh, VBA isn't for Win32 API programming. It's for COM object programming.

Ankur
Tuesday, May 11, 2004

>Eh, VBA isn't for Win32 API programming. It's for COM object programming.

Yes, but callbacks are a feature that are used in the Win32 API.

Sathyaish Chakravarthy
Tuesday, May 11, 2004

First of all VB/VBA has supported callbacks for quite a while through the use of the AddressOf operator (which creates a thunk on the fly).

It's required if you want to call certain functions in the Windows API that return their results by calling a function, the pointer to which you pass in. For example, functions which enumerate things in Windows often work this way. Also it's required because a lot of things in Windows require you to implement a WndProc (window procedure) to receive notifications.

Joel Spolsky
Fog Creek Software
Tuesday, May 11, 2004

I know that.

http://visualbasic.ittoolbox.com/code/d.asp?i=7&d=1498&a=s

http://visualbasic.ittoolbox.com/code/d.asp?i=7&d=1500&a=s

But the wikipedia said VBA didn't support callbacks and that was one limitation. I was wondering why.

Sathyaish Chakravarthy
Tuesday, May 11, 2004

BTW, it was like winning a lottery to hear from Joel. :-)

Sathyaish Chakravarthy
Tuesday, May 11, 2004

AddressOf is really a cheap hack.  VB doesn't support first-class function values like most other languages, but with AddressOf is supports it halfway.  Yes you can get the address of a function but you can't invoke a function by address (unless that function is a message processor and only then with the Win32 function CallWndProc).  All you can do to simulate this behavior is take generic dispatch objects instead of function pointers and ensure that the objects support the necessary functions.


Tuesday, May 11, 2004

But, this one

http://visualbasic.ittoolbox.com/code/d.asp?i=7&d=1500&a=s

is a wrong implementation, I realized an year later. I actually knew that *almost* when I was coding but I had to post it since I was doing it from a cyber cafe when I was jobless and I couldn't keep the meter running just to refactor another implementation.

Sathyaish Chakravarthy
Tuesday, May 11, 2004

>AddressOf is really a cheap hack.  VB doesn't support first-class function values like most other languages, but with AddressOf is supports it halfway.  Yes you can get the address of a function but you can't invoke a function by address (unless that function is a message processor and only then with the Win32 function CallWndProc).  All you can do to simulate this behavior is take generic dispatch objects instead of function pointers and ensure that the objects support the necessary functions.

But that applies to Visual Basic as well. Ah, so I might have as well misconstrued the information there as if it refered only to VBA. So he was generally criticizing the lack of the ability to call a function via its pointer. Yeah, you're right, we can still fake a function pointer in VB with AddressOf by calling a Dummy() with the address of the function as a param, but we can't call it then. So, it's basically no use.

Sathyaish Chakravarthy
Tuesday, May 11, 2004

Wikipedia is wrong?


Tuesday, May 11, 2004

>Wikipedia is wrong?

I wouldn't think that, although it is possible. But in this case, I realize what the paragraph meant probably was the lack of the ability in _both_ VB and VBA to use callbacks, outside the limitations of the AddressOf operator. The AddressOf also has limits. It can only be used with API calls. You can't for e.g implement your own callbacks. If I remember correctly, the AddressOf also has to be the last param to a function's arguments. Most importantly, it can not be used except as an argument to a function or a sub procedure. That is why if you have to assign a function pointer, say, to a structure, you'd have a workaround, because you can't use AddressOf directly.

You'll say

Type WNDCLASS
    uint cbSize;
    ...blah..
    lpszMenuName;
    lpfnWndProc;
End Type


Declare Function MyWndProc (hWnd, msg, wParam, lParam)

Instantiate it,

Dim wc as WNDPROC

<WRONG>
With wc
    .lpfnWndProc = (WNDPROC)AddressOf MyWndProc
End With
</WRONG>

You'll have to make a hack,

With wc
    .lpfnWndProc = Dummy(AddressOf MyWndProc)
End With

Function Dummy (ByVal FnPointer as Long) as Long
    Dummy = FnPointer
End Function

Then, even when you have a function pointer, you can't call the function using it. Probably this was all he was trying to say.

Sathyaish Chakravarthy
Tuesday, May 11, 2004

I seem to recall that VBA5 didn't have the AddressOf function but that it was in VB5. I think the VBA6 releases fixed this as a problem.
(Either that or the version of VBA that shipped with Access)
Basically it's an old meme passed around and repeated.

Peter Ibbotson
Tuesday, May 11, 2004

Correct! They had it from VB5. About VBA5, I wouldn't know, because I never used a callback with VBA ever. Oh no, I used it.

Hey, hang on! That's a damn lie that VBA provides no support for callbacks. It does. I suddenly remember, I used one of the enumeration functions while generating a power point slide presentation from an data in an Access database, only a few months ago.

Sathyaish Chakravarthy
Tuesday, May 11, 2004

Then you may update the article on Wikipedia.

GP
Tuesday, May 11, 2004

Sath, you can't do something like:

typedef void (*PFUNC)(int);
void exec(PFUNC pf) { pf(99); }

There are places where you can stick a function and have it get called by some part of the VB or Win32 framework, but VB doesn't have a function value type.  The best you can do is expose named functions via dispatch objects.


Tuesday, May 11, 2004


Why would anyone care that you can't *call* through a function pointer resolved by AddressOf from within VB code?  There are several much cleaner and safer ways to provide callbacks within your own code.

For example, define an interface with the signature of the callback, and implement it from any class that needs it.  Or use events.  You can use strongly typed interfaces to do this. 

If you need to pass a function pointer to be used as a callback from C code, use AddressOf and make sure you specified the parameters properly.  This feature was intentionally designed to work around API issues, not to enable a new callback technique for strictly VB code.

Seriously,  articles like that are prime examples of programmers trying to force their limited view on other programming environments, rather than learning how the new environment works.

Craig
Tuesday, May 11, 2004

>For example, define an interface with the signature of
>the callback, and implement it from any class that needs
>it.  Or use events.

That's exactly what I said craig, and I do understand the way that VB works from ITypeLib to 'byval as string'.  There are several problems where function pointers (and member function pointers) are a nice simple fit ... especially if type safety can be enforced.  VB doesn't have those features, so for some problems you have to be more verbose than necessary.


Tuesday, May 11, 2004

> AddressOf is really a cheap hack.

Yes but cheap hack is a first class paradigm in VBA.

christopher baus (www.baus.net)
Tuesday, May 11, 2004

Sathyaish,

<quote>
I read this statement from the Wikipedia and needed some supplementary text to elaborate it. Would you please mind?

"VBA is functionally rich and extremely flexible but it does have some important limitations, most notably in its ability to handle callback functions, a fundamental requirement of a "full" Windows programming language."
</quote>

If you really are interested (and not just trolling), read:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbenlr98/html/vaoprAddressOf.asp

and

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/html/vbconpassingfunctionpointerstodllprocedurestypelibraries.asp

Note especially lines like:

"Basic to Basic" function pointers are not supported. Pointers to Visual Basic functions cannot be passed within Visual Basic itself. Currently, only pointers from Visual Basic to a DLL function are supported.

Note that I would dispute the use of the terms 'fundamental requirement' or 'full' on the Wiki page - but it wouldn't be the first time VB was claimed to be a 'toy' language.

Seeya

Anon
Tuesday, May 11, 2004

"Pointers to Visual Basic functions cannot be passed within Visual Basic itself. Currently, only pointers from Visual Basic to a DLL function are supported."

Well, this may be technically correct, depending on how you define pointer. But Visual Basic does give you a couple ways to pass functions back and forth -- the CallByName() function, and the Eval() function.

Jordan Lev
Wednesday, May 12, 2004

*  Recent Topics

*  Fog Creek Home