--- 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