ExternalLibraryFunction.st
changeset 23228 63b599c0c272
parent 23227 7fa1f7a52a26
child 23785 617f45e9fffa
equal deleted inserted replaced
23227:7fa1f7a52a26 23228:63b599c0c272
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 2004 by eXept Software AG
     4  COPYRIGHT (c) 2004 by eXept Software AG
     3 	      All Rights Reserved
     5 	      All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
   200                                                                 [exEnd]
   202                                                                 [exEnd]
   201 
   203 
   202   Synchronous vs. Asynchronous calls:
   204   Synchronous vs. Asynchronous calls:
   203 
   205 
   204     by default, foreign function calls are synchronous, effectively blocking the whole ST/X system
   206     by default, foreign function calls are synchronous, effectively blocking the whole ST/X system
   205     (that is by purpose,´because most C-code is not prepared for being interrupted, and also, normal
   207     (that is by purpose,´because most C-code is not prepared for being interrupted, and also, normal
   206      code is not prepared for a garbage collector to move objects around, while another C thread might
   208      code is not prepared for a garbage collector to move objects around, while another C thread might
   207      access the data...).
   209      access the data...).
   208     Therefore, the following will block all ST/X activity for 10 seconds
   210     Therefore, the following will block all ST/X activity for 10 seconds
   209     (try interacting with the launcher while the Sleep is performing):
   211     (try interacting with the launcher while the Sleep is performing):
   210 
   212 
   436 
   438 
   437     |oldPath|
   439     |oldPath|
   438 
   440 
   439     oldPath := self dllPath.
   441     oldPath := self dllPath.
   440     oldPath notNil ifTrue:[
   442     oldPath notNil ifTrue:[
   441         self dllPath:(oldPath asOrderedCollection copyWithout:aDirectoryPathName)
   443         self dllPath:(oldPath copyWithout:aDirectoryPathName)
   442     ].
   444     ].
   443 
   445 
   444     "
   446     "
   445      self dllPath.
   447      |prevDllPath|
       
   448 
       
   449      prevDllPath := self dllPath.
       
   450      self removeFromDllPath:'C:\aaa\bbb'.
   446      self addToDllPath:'C:\aaa\bbb'.
   451      self addToDllPath:'C:\aaa\bbb'.
   447      self dllPath.
   452      self assert:self dllPath size = (prevDllPath size + 1).
   448      self removeFromDllPath:'C:\aaa\bbb'.
   453      self removeFromDllPath:'C:\aaa\bbb'.
   449      self dllPath.
   454      self assert:self dllPath size = (prevDllPath size).
   450     "
   455     "
       
   456 
       
   457     "Modified (comment): / 23-07-2018 / 11:16:26 / Stefan Vogel"
   451 ! !
   458 ! !
   452 
   459 
   453 !ExternalLibraryFunction class methodsFor:'constants'!
   460 !ExternalLibraryFunction class methodsFor:'constants'!
   454 
   461 
   455 callTypeAPI
   462 callTypeAPI
  1049      Returns a handle or nil.
  1056      Returns a handle or nil.
  1050      Notice the dllMapping mechanism, which can be used to silently load different dlls.
  1057      Notice the dllMapping mechanism, which can be used to silently load different dlls.
  1051      This is useful, if some code has a hardcoded dll-name in it, which needs to be changed,
  1058      This is useful, if some code has a hardcoded dll-name in it, which needs to be changed,
  1052      but you do not want or cannot recompile the methods (i.e. no source avail)"
  1059      but you do not want or cannot recompile the methods (i.e. no source avail)"
  1053 
  1060 
  1054     |handle nameString filename dllPaths|
  1061     |handle nameString filename dllPaths hasSuffix|
  1055 
  1062 
  1056     ObjectFileLoader isNil ifTrue:[
  1063     ObjectFileLoader isNil ifTrue:[
  1057         "no libcomp loaded"
  1064         "no libcomp loaded"
  1058         ^ self primitiveFailed:'libcomp:ObjectFileLoader is not available'.
  1065         ^ self primitiveFailed:'libcomp:ObjectFileLoader is not available'.
  1059     ].
  1066     ].
  1067     DllMapping notNil ifTrue:[
  1074     DllMapping notNil ifTrue:[
  1068         filename := DllMapping at:filename ifAbsent:[ filename ]
  1075         filename := DllMapping at:filename ifAbsent:[ filename ]
  1069     ].
  1076     ].
  1070 
  1077 
  1071     filename := filename asFilename.
  1078     filename := filename asFilename.
  1072     nameString := filename name.
       
  1073 
  1079 
  1074     "try to load, maybe the system knows where to find the dll"
  1080     "try to load, maybe the system knows where to find the dll"
  1075     handle := ObjectFileLoader loadDynamicObject:filename.
  1081     handle := ObjectFileLoader loadDynamicObject:filename.
  1076     handle notNil ifTrue:[^ handle ].
  1082     handle notNil ifTrue:[
  1077 
  1083         ^ handle
  1078     filename isAbsolute ifFalse:[
  1084     ].
       
  1085 
       
  1086     nameString := filename name.
       
  1087     hasSuffix := filename suffix notEmpty.
       
  1088 
       
  1089     filename isAbsolute ifTrue:[
       
  1090         hasSuffix ifFalse:[
       
  1091             "/ try again with the OS-specific dll-extension
       
  1092             ObjectFileLoader sharedLibrarySuffixes do:[:eachPossibleSuffix |
       
  1093                 handle := ObjectFileLoader loadDynamicObject:(filename withSuffix:eachPossibleSuffix).
       
  1094                 handle notNil ifTrue:[
       
  1095                     ^ handle
       
  1096                 ].
       
  1097             ].    
       
  1098         ].
       
  1099     ] ifFalse:[
  1079         "First ask the class defining the ExternalFunction for the location of the dlls ..."
  1100         "First ask the class defining the ExternalFunction for the location of the dlls ..."
  1080         dllPaths := #().
  1101         dllPaths := #().
  1081         owningClass notNil ifTrue:[
  1102         owningClass notNil ifTrue:[
  1082             dllPaths := owningClass dllPath ? #().
  1103             dllPaths := owningClass dllPath.
  1083         ].
  1104         ].
  1084         ".. then ask the system"
  1105         ".. then ask the system .. and the settings"
  1085         dllPaths := dllPaths, (self class dllPath ? #()).
  1106         dllPaths := dllPaths, self class dllPath, UserPreferences current dllPath.
  1086         ".. and the settings"
       
  1087         dllPaths := dllPaths,(UserPreferences current dllPath ? #()).
       
  1088 
  1107 
  1089         dllPaths do:[:eachDirectory |
  1108         dllPaths do:[:eachDirectory |
  1090             |libraryName|
  1109             |libraryName|
  1091 
  1110 
  1092             libraryName := eachDirectory asFilename construct:nameString.
  1111             libraryName := eachDirectory asFilename construct:nameString.
  1093             libraryName suffix isEmpty ifTrue:[
  1112             hasSuffix ifTrue:[
       
  1113                 handle := ObjectFileLoader loadDynamicObject:libraryName.
       
  1114                 handle notNil ifTrue:[
       
  1115                     ^ handle
       
  1116                 ].
       
  1117             ] ifFalse:[        
  1094                 ObjectFileLoader sharedLibrarySuffixes do:[:eachPossibleSuffix |
  1118                 ObjectFileLoader sharedLibrarySuffixes do:[:eachPossibleSuffix |
  1095                     handle := ObjectFileLoader loadDynamicObject:(libraryName withSuffix:eachPossibleSuffix).
  1119                     handle := ObjectFileLoader loadDynamicObject:(libraryName withSuffix:eachPossibleSuffix).
  1096                     handle notNil ifTrue:[^ handle].
  1120                     handle notNil ifTrue:[
       
  1121                         ^ handle
       
  1122                     ].
  1097                 ].    
  1123                 ].    
  1098             ] ifFalse:[        
       
  1099                 handle := ObjectFileLoader loadDynamicObject:libraryName.
       
  1100                 handle notNil ifTrue:[^ handle ].
       
  1101             ].
  1124             ].
  1102         ].
  1125         ].
  1103     ].
  1126     ].
  1104 
  1127 
  1105     filename suffix isEmpty ifTrue:[
       
  1106         "/ try again with the OS-specific dll-extension
       
  1107         ObjectFileLoader sharedLibrarySuffixes do:[:eachPossibleSuffix |
       
  1108             handle := self loadLibrary:(filename withSuffix:eachPossibleSuffix).
       
  1109             handle notNil ifTrue:[^ handle].
       
  1110         ].    
       
  1111     ].
       
  1112 
  1128 
  1113     "/ check for: the dll-path in:
  1129     "/ check for: the dll-path in:
  1114     "/      - owningClass dllPath
  1130     "/      - owningClass dllPath
  1115     "/      - self class dllPath
  1131     "/      - self class dllPath
  1116     "/ check for: the dll-name mapping
  1132     "/ check for: the dll-name mapping
  1121     ObjectFileLoader::ObjectFileLoadError
  1137     ObjectFileLoader::ObjectFileLoadError
  1122         raiseErrorString:('Cannot find or load dll/module: "%1" (check dllPath settings)' bindWith:nameString).
  1138         raiseErrorString:('Cannot find or load dll/module: "%1" (check dllPath settings)' bindWith:nameString).
  1123     ^ nil
  1139     ^ nil
  1124 
  1140 
  1125     "Modified: / 13-02-2017 / 01:14:05 / cg"
  1141     "Modified: / 13-02-2017 / 01:14:05 / cg"
  1126     "Modified: / 22-07-2018 / 15:18:33 / Stefan Vogel"
  1142     "Modified: / 22-07-2018 / 16:34:24 / Stefan Vogel"
  1127 !
  1143 !
  1128 
  1144 
  1129 prepareInvoke
  1145 prepareInvoke
  1130     "called before invoked.
  1146     "called before invoked.
  1131      When called the very first time, moduleHandle is nil,
  1147      When called the very first time, moduleHandle is nil,