ExternalFunctionCallback.st
branchjv
changeset 17728 bbc5fa73dfab
parent 17711 39faaaf888b4
child 17735 6a5bc05f696a
--- a/ExternalFunctionCallback.st	Sun Aug 16 18:14:23 2009 +0100
+++ b/ExternalFunctionCallback.st	Wed Aug 19 17:14:36 2009 +0100
@@ -260,13 +260,13 @@
     and handed out to C. (you can also hand out the callBack directly - as it is a subclass of
     ExternalBytes.
     The actual action of the callback can be changed (at any time later) with:
-	cb action:[:args | Transcript showCR:args. true].
+        cb action:[:args | Transcript showCR:args. true].
 
-    Eventually, the callback should be released:
-	cb release.
+    Eventually, the callback MUST be released:
+        cb release.
 
     [author:]
-	Claus Gittinger
+        Claus Gittinger
 "
 !
 
@@ -291,6 +291,57 @@
 "
 ! !
 
+!ExternalFunctionCallback class methodsFor:'common callbacks'!
+
+callbackFor:aBlock returnType:returnType argumentTypes:argumentTypes
+    "generate a callback for the ErrorCallbackProc signature:
+        ErrorCallbackProc(HWND hWnd, int nErrID, LPTSTR lpErrorText)
+     which, can be given to an external API call and which invokes the
+     three arg block when clled.
+     Do not forget to eventually release the callback to avoid a memory leak."
+
+    |cb|
+
+    self assert:(aBlock numArgs == argumentTypes size).
+
+    cb := ExternalFunctionCallback new.
+    cb returnType:returnType argumentTypes:argumentTypes.
+    cb beCallTypeWINAPI.
+    cb generateClosure.
+    cb action:aBlock.
+    "/ ^ cb code.  'can be passed to C'.
+    ^ cb
+
+    "
+     |cb|
+
+     cb := self errorCallbackProcFor:[:a1 :a2 :a3 | Transcript showCR:('%1 %2 %3' bindWith:a1 with:a2 with:a3)].
+     ExternalFunctionCallback testCall:cb withArguments:#(#[1 2 3] 456 'hello').
+     cb release
+    "
+!
+
+errorCallbackProcFor:aThreeArgBlock
+    "generate a callback for the ErrorCallbackProc signature:
+        ErrorCallbackProc(HWND hWnd, int nErrID, LPTSTR lpErrorText)
+     which, can be given to an external API call and which invokes the
+     three arg block when clled.
+     Do not forget to eventually release the callback to avoid a memory leak."
+
+    ^ self 
+        callbackFor:aThreeArgBlock 
+        returnType:#long 
+        argumentTypes:#(handle int charPointer)
+
+    "
+     |cb|
+
+     cb := self errorCallbackProcFor:[:a1 :a2 :a3 | Transcript showCR:('%1 %2 %3' bindWith:a1 with:a2 with:a3)].
+     ExternalFunctionCallback testCall:cb withArguments:#(#[1 2 3] 456 'hello').
+     cb release
+    "
+! !
+
 !ExternalFunctionCallback class methodsFor:'constants'!
 
 callTypeAPI
@@ -326,26 +377,48 @@
 
 testCall:aCallback withArgument:arg
     "a simple test, if I can be called"
+
+    self testCall:aCallback withArguments:(Array with:arg)
+!
+
+testCall:aCallback withArguments:args
+    "a simple test, if I can be called"
 %{
+#   define MAX_ARGS 5
     INTFUNC f = __externalAddressVal(aCallback);
     INT result;
-    void *c_arg = 0;
+    int i;
+    void *c_args[MAX_ARGS];
+
+    if (! __isArray(args))
+        goto badArg;
+    if (__arraySize(args) > MAX_ARGS)
+        goto badArg;
+
+    for (i=0; i < __arraySize(args); i++) {
+        OBJ arg = __ArrayInstPtr(args)->a_element[i];
 
-    if (__isSmallInteger(arg)) {
-	c_arg = (void *)(__intVal(arg));
-    } else {
-	if (arg == true) {
-	    c_arg = (void *)1;
-	} else {
-	   if (__isString(arg)) {
-		c_arg = (void *)__stringVal(arg);
-	   }
-	}
+        if (__isSmallInteger(arg)) {
+            c_args[i] = (void *)(__intVal(arg));
+        } else if (arg == true) {
+            c_args[i] = (void *)1;
+        } else if (arg == false) {
+            c_args[i] = (void *)0;
+        } else if (__isString(arg)) {
+            c_args[i] = (void *)__stringVal(arg);
+        } else if (__isByteArray(arg)) {
+            c_args[i] = (void *)__byteArrayVal(arg);
+        } else
+            goto badArg;
     }
-    fprintf(stderr, "ExternalFunctionCallback: calling callBack %x(%x)\n", f, c_arg);
-    result = (*f)(c_arg);
+    fprintf(stderr, "ExternalFunctionCallback: calling callBack %x(%x, %x)\n", f, c_args[0], c_args[1]);
+    result = (*f)(c_args[0], c_args[1], c_args[2], c_args[3], c_args[4]);
     fprintf(stderr, "ExternalFunctionCallback: result from callBack is %x\n", result);
-%}
+    RETURN(true);
+
+badArg: ;
+%}.
+    self error:'bad argument'
 ! !
 
 !ExternalFunctionCallback methodsFor:'accessing'!
@@ -746,15 +819,15 @@
 
     __INST(code_) = 0;
     if (pcl) {
-	free(pcl);
+        free(pcl);
+        RETURN(self);
     }
 %}.
     self invalidateReference.
-
 ! !
 
 !ExternalFunctionCallback class methodsFor:'documentation'!
 
 version
-    ^ '$Id: ExternalFunctionCallback.st 10447 2009-06-14 13:09:55Z vranyj1 $'
+    ^ '$Id: ExternalFunctionCallback.st 10467 2009-08-19 16:14:36Z vranyj1 $'
 ! !