Following on from my "Parting words" at [1] I'd like to add the following...
FFIExternalEnumerationType >> callbackReturnOn: callbackContext for: anObject
^ super callbackReturnOn: callbackContext for: anObject value
but I'm seeking some expert feedback before logging an issue.
For discussion background, here is a reference C program that sets up the framework for a callback that returns an enumeration...
----------example.c
#include <stdio.h>
typedef enum {
A = 1,
B = 2,
C = 3
} CallBackReturnValue;
CallBackReturnValue callbackFn() {
return B;
}
CallBackReturnValue callout( CallBackReturnValue (*callback)() )
{
return callback();
}
int main()
{
printf("%d\n", callout(callbackFn) );
return 0;
}
----------
And validation...
$ gcc -Wall -Werror example.c
$ ./a.out
2
----------
Now after deleting main() and callback(), then compiling to a shared library per [2]...
$ gcc -c -Wall -Werror -fpic example.c
$ gcc -shared -o passthru.so example.o
$ cp example.so /tmp
the Pharo equivalent is....
FFIExternalEnumeration subclass: #CallBackReturnValue
instanceVariableNames: ''
classVariableNames: ''
package: 'AAAExample'
CallBackReturnValue class >> enumDecl
^ #( A 1
B 2
C 3 )
CallBackReturnValue class >> initialize
self initializeEnumeration
And evaluate "CallBackReturnValue initialize."
FFILibrary subclass: #Example
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: 'CallBackReturnValue'
package: 'AAAExample'
Example >> unixModuleName
^ '/tmp/example.so'
Example class >> callout: callbackBlock
^ self ffiCall: #( int callout ( FFICallback callbackBlock ) ) module: Example
Example class >> doCallback
| callbackFn |
callbackFn :=
FFICallback
signature: #( CallBackReturnValue ( void ) )
block: [ B ].
^ Example callout: callbackFn.
-----
But "Example doCallback"
produces error in VMCallbackContext32>>wordResult: anInteger
where anInteger is aCallBackReturnValue(#B)
rather than 2
I can resolve this using...
callbackFn :=
FFICallback
signature: #( CallBackReturnValue ( void ) )
block: [ B value ]. "<==="
but the original direct use of the enumeration "B" directly is nicer.
This can be facilitated by moving #value as follows...
FFIExternalEnumerationType >> callbackReturnOn: callbackContext for: anObject
^ super callbackReturnOn: callbackContext for: anObject value "<=="
where the existing method for super is...
FFIExternalType >> callbackReturnOn: callbackContext for: anObject
^ callbackContext wordResult: anObject
Anyone see a problem with that addition?
btw, Would that example be useful for the book?
cheers -ben