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