ExternalLibraryFunction.st
changeset 14659 410089913ca1
parent 14632 6fe0dc1d5377
child 14729 1432f384b1cc
child 18011 deb0c3355881
equal deleted inserted replaced
14658:6c0c3a9eb2c2 14659:410089913ca1
    11 "
    11 "
    12 "{ Package: 'stx:libbasic' }"
    12 "{ Package: 'stx:libbasic' }"
    13 
    13 
    14 ExternalFunction subclass:#ExternalLibraryFunction
    14 ExternalFunction subclass:#ExternalLibraryFunction
    15 	instanceVariableNames:'flags moduleName returnType argumentTypes owningClass'
    15 	instanceVariableNames:'flags moduleName returnType argumentTypes owningClass'
    16 	classVariableNames:'DLLPATH FLAG_VIRTUAL FLAG_NONVIRTUAL FLAG_ASYNC
    16 	classVariableNames:'DLLPATH FLAG_VIRTUAL FLAG_NONVIRTUAL FLAG_OBJECTIVEC FLAG_ASYNC
    17 		FLAG_UNLIMITEDSTACK FLAG_RETVAL_IS_CONST CALLTYPE_MASK
    17 		FLAG_UNLIMITEDSTACK FLAG_RETVAL_IS_CONST CALLTYPE_MASK
    18 		CALLTYPE_API CALLTYPE_C CALLTYPE_OLE CALLTYPE_V8 CALLTYPE_V9
    18 		CALLTYPE_API CALLTYPE_C CALLTYPE_OLE CALLTYPE_V8 CALLTYPE_V9
    19 		CALLTYPE_UNIX64 DllMapping'
    19 		CALLTYPE_UNIX64 DllMapping'
    20 	poolDictionaries:''
    20 	poolDictionaries:''
    21 	category:'System-Support'
    21 	category:'System-Support'
    26 
    26 
    27 #ifdef HAVE_FFI
    27 #ifdef HAVE_FFI
    28 # include <ffi.h>
    28 # include <ffi.h>
    29 # define MAX_ARGS    128
    29 # define MAX_ARGS    128
    30 
    30 
       
    31 # ifdef USE_STANDARD_FFI
       
    32 #  define __get_ffi_type_sint() &ffi_type_sint
       
    33 #  define __get_ffi_type_sint8() &ffi_type_sint8
       
    34 #  define __get_ffi_type_sint16() &ffi_type_sint16
       
    35 #  define __get_ffi_type_sint32() &ffi_type_sint32
       
    36 #  define __get_ffi_type_sint64() &ffi_type_sint64
       
    37 #  define __get_ffi_type_uint() &ffi_type_uint
       
    38 #  define __get_ffi_type_uint8() &ffi_type_uint8
       
    39 #  define __get_ffi_type_uint16() &ffi_type_uint16
       
    40 #  define __get_ffi_type_uint32() &ffi_type_uint32
       
    41 #  define __get_ffi_type_uint64() &ffi_type_uint64
       
    42 #  define __get_ffi_type_float() &ffi_type_float
       
    43 #  define __get_ffi_type_double() &ffi_type_double
       
    44 #  define __get_ffi_type_void() &ffi_type_void
       
    45 #  define __get_ffi_type_pointer() &ffi_type_pointer
       
    46 # else
    31 extern ffi_type *__get_ffi_type_sint();
    47 extern ffi_type *__get_ffi_type_sint();
    32 extern ffi_type *__get_ffi_type_sint8();
    48 extern ffi_type *__get_ffi_type_sint8();
    33 extern ffi_type *__get_ffi_type_sint16();
    49 extern ffi_type *__get_ffi_type_sint16();
    34 extern ffi_type *__get_ffi_type_sint32();
    50 extern ffi_type *__get_ffi_type_sint32();
    35 extern ffi_type *__get_ffi_type_sint64();
    51 extern ffi_type *__get_ffi_type_sint64();
    40 extern ffi_type *__get_ffi_type_uint64();
    56 extern ffi_type *__get_ffi_type_uint64();
    41 extern ffi_type *__get_ffi_type_float();
    57 extern ffi_type *__get_ffi_type_float();
    42 extern ffi_type *__get_ffi_type_double();
    58 extern ffi_type *__get_ffi_type_double();
    43 extern ffi_type *__get_ffi_type_void();
    59 extern ffi_type *__get_ffi_type_void();
    44 extern ffi_type *__get_ffi_type_pointer();
    60 extern ffi_type *__get_ffi_type_pointer();
       
    61 # endif
    45 
    62 
    46 #endif
    63 #endif
    47 
    64 
    48 %}
    65 %}
    49 ! !
    66 ! !
   213 
   230 
   214     DLLPATH isNil ifTrue:[
   231     DLLPATH isNil ifTrue:[
   215 	DLLPATH := #('.').
   232 	DLLPATH := #('.').
   216 	FLAG_VIRTUAL := %{ __MKSMALLINT(__EXTL_FLAG_VIRTUAL) %}.                "/ a virtual c++ call
   233 	FLAG_VIRTUAL := %{ __MKSMALLINT(__EXTL_FLAG_VIRTUAL) %}.                "/ a virtual c++ call
   217 	FLAG_NONVIRTUAL := %{ __MKSMALLINT(__EXTL_FLAG_NONVIRTUAL) %}.          "/ a non-virtual c++ call
   234 	FLAG_NONVIRTUAL := %{ __MKSMALLINT(__EXTL_FLAG_NONVIRTUAL) %}.          "/ a non-virtual c++ call
       
   235 	FLAG_OBJECTIVEC := %{ __MKSMALLINT(__EXTL_FLAG_OBJECTIVEC) %}.          "/ an objectiveC message send
   218 	FLAG_UNLIMITEDSTACK := %{ __MKSMALLINT(__EXTL_FLAG_UNLIMITEDSTACK) %}.  "/ unlimitedstack under unix
   236 	FLAG_UNLIMITEDSTACK := %{ __MKSMALLINT(__EXTL_FLAG_UNLIMITEDSTACK) %}.  "/ unlimitedstack under unix
   219 	FLAG_ASYNC := %{ __MKSMALLINT(__EXTL_FLAG_ASYNC) %}.                    "/ async under win32
   237 	FLAG_ASYNC := %{ __MKSMALLINT(__EXTL_FLAG_ASYNC) %}.                    "/ async under win32
   220 	FLAG_RETVAL_IS_CONST := %{ __MKSMALLINT(__EXTL_FLAG_RETVAL_IS_CONST) %}."/ return value is not to be registered for finalization
   238 	FLAG_RETVAL_IS_CONST := %{ __MKSMALLINT(__EXTL_FLAG_RETVAL_IS_CONST) %}."/ return value is not to be registered for finalization
   221 
   239 
   222 	CALLTYPE_API := %{ __MKSMALLINT(__EXTL_CALLTYPE_API) %}.                "/ WINAPI-call (win32 only)
   240 	CALLTYPE_API := %{ __MKSMALLINT(__EXTL_CALLTYPE_API) %}.                "/ WINAPI-call (win32 only)
   385     flags := (flags ? 0) bitOr: FLAG_VIRTUAL.
   403     flags := (flags ? 0) bitOr: FLAG_VIRTUAL.
   386 
   404 
   387     "Created: / 01-08-2006 / 13:56:48 / cg"
   405     "Created: / 01-08-2006 / 13:56:48 / cg"
   388 !
   406 !
   389 
   407 
       
   408 beObjectiveC
       
   409     "specify this as an objective-c message send"
       
   410 
       
   411     flags := (flags ? 0) bitOr: FLAG_OBJECTIVEC.
       
   412 
       
   413     "Created: / 01-08-2006 / 13:56:48 / cg"
       
   414 !
       
   415 
   390 callTypeNumber
   416 callTypeNumber
   391     ^ (flags ? 0) bitAnd: CALLTYPE_MASK.
   417     ^ (flags ? 0) bitAnd: CALLTYPE_MASK.
   392 
   418 
   393     "Created: / 01-08-2006 / 15:12:10 / cg"
   419     "Created: / 01-08-2006 / 15:12:10 / cg"
   394 !
   420 !
   405     "is this a virtual or non-virtual c++-function ?"
   431     "is this a virtual or non-virtual c++-function ?"
   406 
   432 
   407     ^ (flags ? 0) bitTest: (FLAG_VIRTUAL bitOr: FLAG_NONVIRTUAL).
   433     ^ (flags ? 0) bitTest: (FLAG_VIRTUAL bitOr: FLAG_NONVIRTUAL).
   408 
   434 
   409     "Created: / 01-08-2006 / 13:56:54 / cg"
   435     "Created: / 01-08-2006 / 13:56:54 / cg"
       
   436 !
       
   437 
       
   438 isObjectiveC
       
   439     "is this an objective-C message?"
       
   440 
       
   441     ^ (flags ? 0) bitTest: FLAG_OBJECTIVEC.
   410 !
   442 !
   411 
   443 
   412 isCallTypeAPI
   444 isCallTypeAPI
   413     ^ ((flags ? 0) bitAnd: CALLTYPE_MASK) == CALLTYPE_API.
   445     ^ ((flags ? 0) bitAnd: CALLTYPE_MASK) == CALLTYPE_API.
   414 
   446 
   820     ^ self invokeFFIwithArguments:arguments forCPPInstance:nil
   852     ^ self invokeFFIwithArguments:arguments forCPPInstance:nil
   821 
   853 
   822     "Modified: / 01-08-2006 / 13:55:35 / cg"
   854     "Modified: / 01-08-2006 / 13:55:35 / cg"
   823 !
   855 !
   824 
   856 
   825 invokeFFIwithArguments:argumentsOrNil forCPPInstance:aCPlusPlusObjectOrNil
   857 invokeFFIwithArguments:argumentsOrNil forCPPInstance:aReceiverOrNil
       
   858     "basic invoke mechanism. Calls the function represented by the receiver with argumentsOrNil.
       
   859      For cplusplus, aReceiverOrNil is required to be an externalStructure like object;
       
   860      for objectiveC, it must be an ObjectiveC object"
       
   861 
   826     |argTypeSymbols returnTypeSymbol failureCode failureInfo returnValue stClass vtOffset
   862     |argTypeSymbols returnTypeSymbol failureCode failureInfo returnValue stClass vtOffset
   827      virtual async unlimitedStack callTypeNumber returnValueClass argValueClass
   863      virtual objectiveC async unlimitedStack callTypeNumber returnValueClass argValueClass
   828      oldReturnType oldArgumentTypes
   864      oldReturnType oldArgumentTypes|
   829     |
       
   830 
   865 
   831     argTypeSymbols := argumentTypes.
   866     argTypeSymbols := argumentTypes.
   832     returnTypeSymbol := returnType.
   867     returnTypeSymbol := returnType.
   833 
   868 
   834     virtual := self isVirtualCPP.
   869     virtual := self isVirtualCPP.
       
   870     objectiveC := self isObjectiveC.
   835     (virtual "or:[self isNonVirtualCPP]") ifTrue:[
   871     (virtual "or:[self isNonVirtualCPP]") ifTrue:[
   836 	aCPlusPlusObjectOrNil isNil ifTrue:[
   872 	aReceiverOrNil isNil ifTrue:[
   837 	    "/ must have a c++ object instance
   873 	    "/ must have a c++ object instance
   838 	    self primitiveFailed.
   874 	    self primitiveFailed.
   839 	].
   875 	].
   840 
   876 
   841 	"/ and it must be a kind of ExternalStructure !!
   877 	"/ and it must be a kind of ExternalStructure !!
   842 	(aCPlusPlusObjectOrNil isKindOf:ExternalStructure) ifFalse:[
   878 	(aReceiverOrNil isKindOf:ExternalStructure) ifFalse:[
   843 	    self primitiveFailed.
   879 	    self primitiveFailed.
   844 	].
   880 	].
   845 	virtual ifTrue:[
   881 	virtual ifTrue:[
   846 	    vtOffset := name.
   882 	    vtOffset := name.
   847 	    (vtOffset between:0 and:10000) ifFalse:[
   883 	    (vtOffset between:0 and:10000) ifFalse:[
   848 		self primitiveFailed.
   884 		self primitiveFailed.
   849 	    ]
   885 	    ]
   850 	].
   886 	].
   851     ] ifFalse:[
   887     ] ifFalse:[
   852 	aCPlusPlusObjectOrNil notNil ifTrue:[
   888 	objectiveC ifTrue:[
   853 	    "/ must NOT have a c++ object instance
   889 	    aReceiverOrNil isNil ifTrue:[
   854 	    self primitiveFailed.
   890 	        "/ must have an objective-c object instance
       
   891 	        self primitiveFailed.
       
   892 	    ].
       
   893 	    (aReceiverOrNil isObjectiveCObject) ifFalse:[
       
   894 		self primitiveFailed
       
   895 	    ]
       
   896 	] ifFalse:[
       
   897 	    aReceiverOrNil notNil ifTrue:[
       
   898 	        "/ must NOT have a c++/objectiveC object instance
       
   899 	        self primitiveFailed.
       
   900 	    ]
   855 	].
   901 	].
   856     ].
   902     ].
   857     async := self isAsync.
   903     async := self isAsync.
   858     unlimitedStack := self isUnlimitedStack.
   904     unlimitedStack := self isUnlimitedStack.
   859     callTypeNumber := self callTypeNumber.
   905     callTypeNumber := self callTypeNumber.
   860     "/ Transcript show:name; show:' async:'; showCR:async.
   906     "/ Transcript show:name; show:' async:'; showCR:async.
   861 
   907 
   862 %{  /* STACK: 100000 */
   908 %{  /* STACK: 100000 */
       
   909 
   863 #ifdef HAVE_FFI
   910 #ifdef HAVE_FFI
   864 # ifdef __GNUC__
   911 # ifdef __GNUC__
   865 #  define HAS_LONGLONG
   912 #  ifndef HAS_LONGLONG
       
   913 #   define HAS_LONGLONG
       
   914 #  endif
   866 # endif
   915 # endif
   867 # if defined(__BORLANDC__) || defined(__VISUALC__)
   916 # if defined(__BORLANDC__) || defined(__VISUALC__)
   868 #  define HAS_INT64
   917 #  define HAS_INT64
   869 # endif
   918 # endif
   870 
   919 
  1021     }
  1070     }
  1022 
  1071 
  1023     /*
  1072     /*
  1024      * validate the c++ object
  1073      * validate the c++ object
  1025      */
  1074      */
  1026     if (aCPlusPlusObjectOrNil != nil) {
  1075     if (aReceiverOrNil != nil) {
  1027 	struct cPlusPlusInstance {
  1076 	struct cPlusPlusInstance {
  1028 	    void **vTable;
  1077 	    void **vTable;
  1029 	};
  1078 	};
  1030 	struct cPlusPlusInstance *inst;
  1079 	struct cPlusPlusInstance *inst;
  1031 
  1080 
  1032 	if (__isExternalAddressLike(aCPlusPlusObjectOrNil)) {
  1081 	if (__isExternalAddressLike(aReceiverOrNil)) {
  1033 	    inst = (void *)(__externalAddressVal(aCPlusPlusObjectOrNil));
  1082 	    inst = (void *)(__externalAddressVal(aReceiverOrNil));
  1034 	} else if (__isExternalBytesLike(aCPlusPlusObjectOrNil)) {
  1083 	} else if (__isExternalBytesLike(aReceiverOrNil)) {
  1035 	    inst = (void *)(__externalBytesVal(aCPlusPlusObjectOrNil));
  1084 	    inst = (void *)(__externalBytesVal(aReceiverOrNil));
  1036 	} else {
  1085 	} else {
  1037 	    __FAIL__(@symbol(InvalidInstance))
  1086 	    __FAIL__(@symbol(InvalidInstance))
  1038 	}
  1087 	}
  1039 	__argValues[0].pointerVal = inst;
  1088 	__argValues[0].pointerVal = inst;
  1040 	__argValuePointersIncludingThis[0] = &(__argValues[0]);
  1089 	__argValuePointersIncludingThis[0] = &(__argValues[0]);
  1524 	    ((oldReturnType ~= returnType) or:[oldArgumentTypes ~= argumentTypes]) ifTrue:[
  1573 	    ((oldReturnType ~= returnType) or:[oldArgumentTypes ~= argumentTypes]) ifTrue:[
  1525 		thisContext restart
  1574 		thisContext restart
  1526 	    ].
  1575 	    ].
  1527 	].
  1576 	].
  1528 	(failureCode == #BadArgForAsyncCall) ifTrue:[
  1577 	(failureCode == #BadArgForAsyncCall) ifTrue:[
  1529 	    ^ self tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aCPlusPlusObjectOrNil
  1578 	    ^ self tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aReceiverOrNil
  1530 	].
  1579 	].
  1531 
  1580 
  1532 	self primitiveFailed.   "see failureCode and failureInfo for details"
  1581 	self primitiveFailed.   "see failureCode and failureInfo for details"
  1533 	^ nil
  1582 	^ nil
  1534     ].
  1583     ].
  1563 
  1612 
  1564     "Created: / 01-08-2006 / 13:56:23 / cg"
  1613     "Created: / 01-08-2006 / 13:56:23 / cg"
  1565     "Modified: / 11-06-2007 / 01:50:36 / cg"
  1614     "Modified: / 11-06-2007 / 01:50:36 / cg"
  1566 !
  1615 !
  1567 
  1616 
  1568 tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aCPlusPlusObjectOrNil
  1617 tryAgainWithAsyncSafeArguments:argumentsOrNil forCPPInstance:aReceiverOrNil
  1569     "invoked by the call primitive, iff GC-unsave arguments where passed to the call.
  1618     "invoked by the call primitive, iff GC-unsave arguments where passed to the call.
  1570      Here, allocate non-movable blocks of memory and copy the arguments into them,
  1619      Here, allocate non-movable blocks of memory and copy the arguments into them,
  1571      then try the call again, copy changed values back, and release the memeory."
  1620      then try the call again, copy changed values back, and release the memeory."
  1572 
  1621 
  1573     |saveArguments anyBadArg result originalToSaveArgMapping|
  1622     |saveArguments anyBadArg result originalToSaveArgMapping|
  1607     anyBadArg ifFalse:[
  1656     anyBadArg ifFalse:[
  1608 	"avoid recursion..."
  1657 	"avoid recursion..."
  1609 	^ self primitiveFailed
  1658 	^ self primitiveFailed
  1610     ].
  1659     ].
  1611 
  1660 
  1612     result := self invokeFFIwithArguments:saveArguments forCPPInstance:aCPlusPlusObjectOrNil.
  1661     result := self invokeFFIwithArguments:saveArguments forCPPInstance:aReceiverOrNil.
  1613 
  1662 
  1614     "/ copy back !!
  1663     "/ copy back !!
  1615     originalToSaveArgMapping keysAndValuesDo:[:arg :saveArg |
  1664     originalToSaveArgMapping keysAndValuesDo:[:arg :saveArg |
  1616 	arg isSymbol ifFalse:[
  1665 	arg isSymbol ifFalse:[
  1617 	    arg replaceFrom:1 to:(arg size) with:saveArg startingAt:1.
  1666 	    arg replaceFrom:1 to:(arg size) with:saveArg startingAt:1.
  1635 ! !
  1684 ! !
  1636 
  1685 
  1637 !ExternalLibraryFunction class methodsFor:'documentation'!
  1686 !ExternalLibraryFunction class methodsFor:'documentation'!
  1638 
  1687 
  1639 version_CVS
  1688 version_CVS
  1640     ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.92 2013-01-08 17:55:11 cg Exp $'
  1689     ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.93 2013-01-16 12:20:15 cg Exp $'
  1641 !
  1690 !
  1642 
  1691 
  1643 version_SVN
  1692 version_SVN
  1644     ^ '§ Id: ExternalLibraryFunction.st 10643 2011-06-08 21:53:07Z vranyj1  §'
  1693     ^ '§ Id: ExternalLibraryFunction.st 10643 2011-06-08 21:53:07Z vranyj1  §'
  1645 ! !
  1694 ! !