ExternalLibraryFunction.st
changeset 14659 410089913ca1
parent 14632 6fe0dc1d5377
child 14729 1432f384b1cc
child 18011 deb0c3355881
--- a/ExternalLibraryFunction.st	Wed Jan 16 12:01:26 2013 +0100
+++ b/ExternalLibraryFunction.st	Wed Jan 16 13:20:15 2013 +0100
@@ -13,7 +13,7 @@
 
 ExternalFunction subclass:#ExternalLibraryFunction
 	instanceVariableNames:'flags moduleName returnType argumentTypes owningClass'
-	classVariableNames:'DLLPATH FLAG_VIRTUAL FLAG_NONVIRTUAL FLAG_ASYNC
+	classVariableNames:'DLLPATH FLAG_VIRTUAL FLAG_NONVIRTUAL FLAG_OBJECTIVEC FLAG_ASYNC
 		FLAG_UNLIMITEDSTACK FLAG_RETVAL_IS_CONST CALLTYPE_MASK
 		CALLTYPE_API CALLTYPE_C CALLTYPE_OLE CALLTYPE_V8 CALLTYPE_V9
 		CALLTYPE_UNIX64 DllMapping'
@@ -28,6 +28,22 @@
 # include <ffi.h>
 # define MAX_ARGS    128
 
+# ifdef USE_STANDARD_FFI
+#  define __get_ffi_type_sint() &ffi_type_sint
+#  define __get_ffi_type_sint8() &ffi_type_sint8
+#  define __get_ffi_type_sint16() &ffi_type_sint16
+#  define __get_ffi_type_sint32() &ffi_type_sint32
+#  define __get_ffi_type_sint64() &ffi_type_sint64
+#  define __get_ffi_type_uint() &ffi_type_uint
+#  define __get_ffi_type_uint8() &ffi_type_uint8
+#  define __get_ffi_type_uint16() &ffi_type_uint16
+#  define __get_ffi_type_uint32() &ffi_type_uint32
+#  define __get_ffi_type_uint64() &ffi_type_uint64
+#  define __get_ffi_type_float() &ffi_type_float
+#  define __get_ffi_type_double() &ffi_type_double
+#  define __get_ffi_type_void() &ffi_type_void
+#  define __get_ffi_type_pointer() &ffi_type_pointer
+# else
 extern ffi_type *__get_ffi_type_sint();
 extern ffi_type *__get_ffi_type_sint8();
 extern ffi_type *__get_ffi_type_sint16();
@@ -42,6 +58,7 @@
 extern ffi_type *__get_ffi_type_double();
 extern ffi_type *__get_ffi_type_void();
 extern ffi_type *__get_ffi_type_pointer();
+# endif
 
 #endif
 
@@ -215,6 +232,7 @@
 	DLLPATH := #('.').
 	FLAG_VIRTUAL := %{ __MKSMALLINT(__EXTL_FLAG_VIRTUAL) %}.                "/ a virtual c++ call
 	FLAG_NONVIRTUAL := %{ __MKSMALLINT(__EXTL_FLAG_NONVIRTUAL) %}.          "/ a non-virtual c++ call
+	FLAG_OBJECTIVEC := %{ __MKSMALLINT(__EXTL_FLAG_OBJECTIVEC) %}.          "/ an objectiveC message send
 	FLAG_UNLIMITEDSTACK := %{ __MKSMALLINT(__EXTL_FLAG_UNLIMITEDSTACK) %}.  "/ unlimitedstack under unix
 	FLAG_ASYNC := %{ __MKSMALLINT(__EXTL_FLAG_ASYNC) %}.                    "/ async under win32
 	FLAG_RETVAL_IS_CONST := %{ __MKSMALLINT(__EXTL_FLAG_RETVAL_IS_CONST) %}."/ return value is not to be registered for finalization
@@ -387,6 +405,14 @@
     "Created: / 01-08-2006 / 13:56:48 / cg"
 !
 
+beObjectiveC
+    "specify this as an objective-c message send"
+
+    flags := (flags ? 0) bitOr: FLAG_OBJECTIVEC.
+
+    "Created: / 01-08-2006 / 13:56:48 / cg"
+!
+
 callTypeNumber
     ^ (flags ? 0) bitAnd: CALLTYPE_MASK.
 
@@ -409,6 +435,12 @@
     "Created: / 01-08-2006 / 13:56:54 / cg"
 !
 
+isObjectiveC
+    "is this an objective-C message?"
+
+    ^ (flags ? 0) bitTest: FLAG_OBJECTIVEC.
+!
+
 isCallTypeAPI
     ^ ((flags ? 0) bitAnd: CALLTYPE_MASK) == CALLTYPE_API.
 
@@ -822,24 +854,28 @@
     "Modified: / 01-08-2006 / 13:55:35 / cg"
 !
 
-invokeFFIwithArguments:argumentsOrNil forCPPInstance:aCPlusPlusObjectOrNil
+invokeFFIwithArguments:argumentsOrNil forCPPInstance:aReceiverOrNil
+    "basic invoke mechanism. Calls the function represented by the receiver with argumentsOrNil.
+     For cplusplus, aReceiverOrNil is required to be an externalStructure like object;
+     for objectiveC, it must be an ObjectiveC object"
+
     |argTypeSymbols returnTypeSymbol failureCode failureInfo returnValue stClass vtOffset
-     virtual async unlimitedStack callTypeNumber returnValueClass argValueClass
-     oldReturnType oldArgumentTypes
-    |
+     virtual objectiveC async unlimitedStack callTypeNumber returnValueClass argValueClass
+     oldReturnType oldArgumentTypes|
 
     argTypeSymbols := argumentTypes.
     returnTypeSymbol := returnType.
 
     virtual := self isVirtualCPP.
+    objectiveC := self isObjectiveC.
     (virtual "or:[self isNonVirtualCPP]") ifTrue:[
-	aCPlusPlusObjectOrNil isNil ifTrue:[
+	aReceiverOrNil isNil ifTrue:[
 	    "/ must have a c++ object instance
 	    self primitiveFailed.
 	].
 
 	"/ and it must be a kind of ExternalStructure !!
-	(aCPlusPlusObjectOrNil isKindOf:ExternalStructure) ifFalse:[
+	(aReceiverOrNil isKindOf:ExternalStructure) ifFalse:[
 	    self primitiveFailed.
 	].
 	virtual ifTrue:[
@@ -849,9 +885,19 @@
 	    ]
 	].
     ] ifFalse:[
-	aCPlusPlusObjectOrNil notNil ifTrue:[
-	    "/ must NOT have a c++ object instance
-	    self primitiveFailed.
+	objectiveC ifTrue:[
+	    aReceiverOrNil isNil ifTrue:[
+	        "/ must have an objective-c object instance
+	        self primitiveFailed.
+	    ].
+	    (aReceiverOrNil isObjectiveCObject) ifFalse:[
+		self primitiveFailed
+	    ]
+	] ifFalse:[
+	    aReceiverOrNil notNil ifTrue:[
+	        "/ must NOT have a c++/objectiveC object instance
+	        self primitiveFailed.
+	    ]
 	].
     ].
     async := self isAsync.
@@ -860,9 +906,12 @@
     "/ Transcript show:name; show:' async:'; showCR:async.
 
 %{  /* STACK: 100000 */
+
 #ifdef HAVE_FFI
 # ifdef __GNUC__
-#  define HAS_LONGLONG
+#  ifndef HAS_LONGLONG
+#   define HAS_LONGLONG
+#  endif
 # endif
 # if defined(__BORLANDC__) || defined(__VISUALC__)
 #  define HAS_INT64
@@ -1023,16 +1072,16 @@
     /*
      * validate the c++ object
      */
-    if (aCPlusPlusObjectOrNil != nil) {
+    if (aReceiverOrNil != nil) {
 	struct cPlusPlusInstance {
 	    void **vTable;
 	};
 	struct cPlusPlusInstance *inst;
 
-	if (__isExternalAddressLike(aCPlusPlusObjectOrNil)) {
-	    inst = (void *)(__externalAddressVal(aCPlusPlusObjectOrNil));
-	} else if (__isExternalBytesLike(aCPlusPlusObjectOrNil)) {
-	    inst = (void *)(__externalBytesVal(aCPlusPlusObjectOrNil));
+	if (__isExternalAddressLike(aReceiverOrNil)) {
+	    inst = (void *)(__externalAddressVal(aReceiverOrNil));
+	} else if (__isExternalBytesLike(aReceiverOrNil)) {
+	    inst = (void *)(__externalBytesVal(aReceiverOrNil));
 	} else {
 	    __FAIL__(@symbol(InvalidInstance))
 	}
@@ -1526,7 +1575,7 @@
 	    ].
 	].
 	(failureCode == #BadArgForAsyncCall) ifTrue:[
-	    ^ self tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aCPlusPlusObjectOrNil
+	    ^ self tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aReceiverOrNil
 	].
 
 	self primitiveFailed.   "see failureCode and failureInfo for details"
@@ -1565,7 +1614,7 @@
     "Modified: / 11-06-2007 / 01:50:36 / cg"
 !
 
-tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aCPlusPlusObjectOrNil
+tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aReceiverOrNil
     "invoked by the call primitive, iff GC-unsave arguments where passed to the call.
      Here, allocate non-movable blocks of memory and copy the arguments into them,
      then try the call again, copy changed values back, and release the memeory."
@@ -1609,7 +1658,7 @@
 	^ self primitiveFailed
     ].
 
-    result := self invokeFFIwithArguments:saveArguments forCPPInstance:aCPlusPlusObjectOrNil.
+    result := self invokeFFIwithArguments:saveArguments forCPPInstance:aReceiverOrNil.
 
     "/ copy back !!
     originalToSaveArgMapping keysAndValuesDo:[:arg :saveArg |
@@ -1637,7 +1686,7 @@
 !ExternalLibraryFunction class methodsFor:'documentation'!
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.92 2013-01-08 17:55:11 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.93 2013-01-16 12:20:15 cg Exp $'
 !
 
 version_SVN