I think the following shows a problem in Dolphin, but I doubt if there's any
way to fix it, so this post is more of a warning for the records than a bug report. I've been attempting to interface to an external library which makes extensive use of callbacks, and been having a Great Deal Of Difficulty (tm). The problem was that whenever I attempted to use one of the exported functions which took a callback as parameter, the call would fail with: Unhandled exception - an InvalidExternalCall('Invalid arg 3: Cannot coerce a BlockCallback to ExternalCallback*') Which seemed odd enough in itself. But what made it really puzzling was that after a while it would start working, and thereafter would work beautifully (modulo the bugs in the external library). I've just worked out what the problem is. My ExternalLibrary's methods are of the form: enumerateSuggestions: aHunspell word: aString callback: anExternalCallback <stdcall: sdword enumerateSuggestions void* char* ExternalCallback*> ^ self invalidCall. That will only work if #asParameter has /already/ been sent to the ExternalCallback in question, since it's only then that it (re-)generates its #thunk. If that hasn't been sent then the VM reports (correctly) that the call failed, and #invalidCall reports (misleadingly) that it was a coercion failure. Since I was playing with this stuff in a workspace, I had one ExternalCallback instance (actually a BlockCallback) which I kept re-using. It wasn't until I happened to send #asParameter to that BlockCallback that it started to work. And from then on it continued, most bafflingly, to work... Applies to D5 and D6. -- chris |
"Chris Uppal" <[hidden email]> wrote in message
news:4440e67f$0$662$[hidden email]... >I think the following shows a problem in Dolphin, but I doubt if there's >any > way to fix it, so this post is more of a warning for the records than a > bug > report. > ... > I've just worked out what the problem is. My ExternalLibrary's methods > are of > the form: > > enumerateSuggestions: aHunspell word: aString callback: > anExternalCallback > <stdcall: sdword enumerateSuggestions void* char* > ExternalCallback*> > ^ self invalidCall. > > That will only work if #asParameter has /already/ been sent to the > ExternalCallback in question, since it's only then that it (re-)generates > its > #thunk. If that hasn't been sent then the VM reports (correctly) that the > call > failed, and #invalidCall reports (misleadingly) that it was a coercion > failure. > This is "by design". It was never intended that ExternalCallbacks should be directly passable as interop parameters, nor that they could be used as the parameter type either. If you look in the base image you'll find callbacks are always declared as lpvoid. It just so happens that because ExternalCallback has the same initial shape as an ExternalStructure (first inst var is a byte object), that it is possible to get away with it if the callback object has been initialised to contain the thunk - i.e. by sending #asParameter. I agree the error reporting could be better, and probably the compiler should not permit ExternalCallback as a parameter type. Regards Blair |
Blair,
> This is "by design". It was never intended that ExternalCallbacks should > be directly passable as interop parameters, nor that they could be used > as the parameter type either. Ok, that makes sense, thanks. > If you look in the base image you'll find > callbacks are always declared as lpvoid. I did look, and would have switched to that way of doing things if I couldn't make it work the way I preferred. I don't like using void*-s unless I have to -- there's too much chance of error with external interfacing so I like (just for once ;-) the more static approach to typing. The existing code seems to use void* more than is necessary, so I didn't realise that in this instance it /was/ necessary. Perhaps it would be worth "adding" ;-) a note to that effect to the ExternalCallback's class comment ? And perhaps too to the relevant section of the education centre ? -- chris |
Free forum by Nabble | Edit this page |