eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'ExternalLibraryFunction':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: ExternalLibraryFunction


Inheritance:

   Object
   |
   +--ExecutableFunction
      |
      +--ExternalFunction
         |
         +--ExternalLibraryFunction

Package:
stx:libbasic
Category:
System-Support
Version:
rev: 1.193 date: 2019/07/22 05:25:53
user: cg
file: ExternalLibraryFunction.st directory: libbasic
module: stx stc-classLibrary: libbasic

Description:


instances of me are used to interface to external library functions (as found in a dll/shared object).
Foreign function calls are based on the FFI library if available.
A limited fallback implementation is provided for systems with no libffi.
(this may have limitations on the supported argument types; for example,
 the x86_64 fallback does not support float/double arguments).
Therefore the fallback should be considered a temporary workaround,
until libffi has been ported.

Inside a method, when a special external-call pragma such as:
    <api: bool MessageBeep(uint)>

is encountered by the parser, the compiler generates a call via
    <correspondingExternalLibraryFunctionObject> invokeWithArguments: argumentArray.
and the correspondingExternalLibraryFunctionObject is kept in the literal array.

In the invoke method, the library is checked to be loaded (and loaded if not already),
the arguments are converted to C and pushed onto the C-stack, the function is called,
and finally, the return value is converted back from C to a smalltalk object.

The parser supports the call-syntax of various other smalltalk dialects:
    Squeak / ST-X:
        <cdecl:   [async] [virtual|nonVirtual][const] returnType functionNameStringOrIndex ( argType1..argTypeN ) module: moduleName >
        <apicall: [async] [virtual|nonVirtual][const] returnType functionNameStringOrIndex ( argType1..argTypeN ) module: moduleName >

    Dolphin:
        <stdcall: [virtual|nonVirtual][const] returnType functionNameStringOrIndex argType1..argTypeN>
        <cdecl:   [virtual|nonVirtual][const] returnType functionNameStringOrIndex argType1..argTypeN>

    ST/V:
        <api: functionName argType1 .. argTypeN returnType>
        <ccall: functionName argType1 .. argTypeN returnType>
        <ole: vFunctionIndex argType1 .. argTypeN returnType>

    VisualWorks:
        <c: ...>
        <c: #define NAME value>


Class protocol:

class initialization
o  addToDllPath: aDirectoryPathName
can be used during initialization, to add more places for dll-loading

usage example(s):

     self addToDllPath:'c:\matrix\API\dll'

o  defaultDLLPath
return a default dll-path, as per operating system

usage example(s):

     self defaultDLLPath

o  dllMapping
allows for dll's to be replaced,
for example, if you want to use the mozilla sqlite dll
C:\Program Files\Mozilla Firefox\mozsqlite3.dll
for the sqlite3, execute:
ExternalLibraryFunction
dllMapping at:'sqlite3'
put: 'C:\Program Files\Mozilla Firefox\mozsqlite3.dll'
for mingw:
ExternalLibraryFunction
dllMapping at:'sqlite3'
put:'C:\mingw64\opt\bin\libsqlite3-0.dll'

o  dllMapping: aDictionary
allows for dll's to be replaced,
for example, if you want to use the mozilla sqlite dll
C:\Program Files\Mozilla Firefox\mozsqlite3.dll
for the sqlite3, execute:
ExternalLibraryFunction
dllMapping at:'sqlite3'
put: 'C:\Program Files\Mozilla Firefox\mozsqlite3.dll'
for mingw:
ExternalLibraryFunction
dllMapping at:'sqlite3'
put:'C:\mingw64\opt\bin\libsqlite3-0.dll'

o  dllMappingAt: baseLibname put: aNameOrPath
allows for dll's to be replaced,
for example, if you want to use the mozilla sqlite dll
C:\Program Files\Mozilla Firefox\mozsqlite3.dll
for the sqlite3, execute:
ExternalLibraryFunction
dllMappingAt:'sqlite3'
put: 'C:\Program Files\Mozilla Firefox\mozsqlite3.dll'
for mingw:
ExternalLibraryFunction
dllMappingAt:'sqlite3'
put:'C:\mingw64\opt\bin\libsqlite3-0.dll'

o  dllPath
provide a default dllPath, where external libraries are searched for

usage example(s):

     ExternalLibraryFunction dllPath

o  dllPath: aCollectionOfDirectoryPathNames
provide a default dllPath, where external libraries are searched for

o  flushModuleHandlesForLibrary: aLibraryName
self flushModuleHandlesForLibrary:'ole32.dll'

o  flushModuleHandlesForWhich: aBlock
self flushModuleHandlesForLibrary:'ole32.dll'

o  initialize
using inline access to corresponding c--defines to avoid duplicate places of knowledge

usage example(s):

DLLPATH := nil.
     self initialize

o  removeFromDllPath: aDirectoryPathName
remove added places from dll-loading

constants
o  callTypeAPI

o  callTypeC

o  callTypeCDecl

o  callTypeMASK

o  callTypeOLE

o  callTypeUNIX64

o  invokeSelectors

debugging
o  verbose: aBoolean
turn on/off tracing of calls

usage example(s):

     ExternalLibraryFunction verbose:true

instance creation
o  name: functionName module: moduleName callType: callTypeSymbol returnType: returnType argumentTypes: argTypes

o  name: functionName module: moduleName returnType: returnType argumentTypes: argTypes

type name mapping
o  adjustAllTypes
because adjustTypes is invoked only once (when the ext-call is first created),
any change in the type mapping (ffiTypeSymbolForType: or mapType) will not
affect existing lib-calls.
Use this, to adjust all thoseafter a change in the type mapping

o  ffiTypeSymbolForType: aType
map aType to one of the ffi-supported ones:
sint8, sint16, sint32, sint64
uint8, uint16, uint32, uint64
long ulong int uint
bool float double void pointer handle

o  mapType: aTypeSymbol toFFI: mappedType
additional user defined type map:
eg. self mapType:#INT8 toFFI:#int8
allows use of INT8 in external function api declarations.
mappedType should be one of the ffi-supported ones:
sint8, sint16, sint32, sint64
uint8, uint16, uint32, uint64
long ulong int uint
bool float double void pointer handle


Instance protocol:

accessing
o  argumentTypes

o  argumentTypesString

o  beAsync
let this execute in a separate thread, in par with the other execution thread(s).
Ignored under unix/linux (until those support multiple threads too).

o  beCallTypeAPI

o  beCallTypeC

o  beCallTypeOLE

o  beCallTypeUNIX64

o  beCallTypeV8

o  beCallTypeV9

o  beCallTypeWINAPI

o  beConstReturnValue
specify that a pointer return value is not to be finalized
(i.e. points to static data or data which is freed by c)

o  beMustFreeReturnValue
specify that a pointer return value is to be freed explicitly by st/x
(i.e. points to mallocd data which is not freed by c)

o  beNonVirtualCPP
specify this as a non-virtual c++-function

o  beObjectiveC
specify this as an objective-c message send

o  beUnlimitedStack
let this execute on the c-stack (as opposed to the thread-stack)
for unlimited auto-sized-stack under unix/linux.
Ignored under windows.

o  beVirtualCPP
specify this as a virtual c++-function

o  callType: aSymbol

o  callTypeNumber

o  isAsync
is this executed in a separate thread, in par with the other execution thread(s) ?

o  isCPPFunction
is this a virtual or non-virtual c++-function ?

o  isCallTypeAPI
is this a windows API-call linkage call.
Attention: this uses a different call API (callee unwinds the stack),
and MUST be declared as such for many Kernel functions.
The calltype API is one of the worst historic garbage kept by MS...

o  isCallTypeC
is this a regular C-call (attention: on windows, there are two kinds of calls)

o  isCallTypeOLE
is this an OLE-object call ? (eg. a virtual c++ call; same as isCallTypeCPP)

o  isConstReturnValue
is the pointer return value not to be finalized
(i.e. points to static data or data which is freed by c)

o  isNonVirtualCPP
is this a non-virtual c++-function ?

o  isObjectiveC
is this an objective-C message?

o  isUnlimitedStack
will this execute on the c-stack (as opposed to the thread-stack)
for unlimited auto-sized-stack under unix/linux.
Ignored under windows.

o  isVirtualCPP
is this a virtual c++-function (same as isCallTypeOLE) ?

o  moduleName

o  mustFreeReturnValue
answer true, if a pointer to some C-datum is returned, which must be freed by ST/X.
(i.e. points to malloc'd data which is NOT freed by c)

o  returnType

o  vtableIndex

inspecting
o  inspectorExtraAttributes
( an extension from the stx:libtool package )
extra (pseudo instvar) entries to be shown in an inspector.

invoking
o  invoke
call the function with no arguments

o  invokeCPPVirtualOn: anInstance
call a CPP virtual function with no arguments

o  invokeCPPVirtualOn: anInstance with: arg
call a CPP virtual function with 1 argument

o  invokeCPPVirtualOn: anInstance with: arg1 with: arg2
call a CPP virtual function with 2 arguments

o  invokeCPPVirtualOn: anInstance with: arg1 with: arg2 with: arg3
call a CPP virtual function with 3 arguments

o  invokeCPPVirtualOn: anInstance with: arg1 with: arg2 with: arg3 with: arg4
call a CPP virtual function with 4 arguments

o  invokeCPPVirtualOn: anInstance withArguments: args
call a CPP virtual function with up to maxArgs (15) arguments

o  invokeObjCOn: anInstance
call an ObjC method with no arguments

o  invokeObjCOn: anInstance withArguments: args
call an ObjC method with up to maxArgs (15) arguments

o  invokeWith: arg
call the function with 1 argument

o  invokeWith: arg1 with: arg2
call the function with 2 arguments

o  invokeWith: arg1 with: arg2 with: arg3
call the function with 3 arguments

o  invokeWith: arg1 with: arg2 with: arg3 with: arg4
call the function with 4 arguments

o  invokeWithArguments: argArray
call the function with up to maxArgs (15) arguments

printing
o  printOn: aStream
(comment from inherited method)
append a printed representation of the receiver to aStream

private
o  adjustTypes
map all those existing type names to a small number of definite ffi type names.
This is needed, because there are so many different C-type names found in code imported
from various Smalltalk dialects' library function call declarations.
For example: all of word, WORD, unsignedShort, ushort, uShort etc. will map to uint16.
Also, this deals with pointer size differences.

o  convertArgument: arg
a chance to convert arguments to one of the primitive (native) types.

o  linkToModule
link this function to the external module.
I.e. retrieve the module handle and the code pointer.
The name of the DLL is retrieved either from the primitive declaration or
the owning instance or its class

o  loadLibrary: dllName
load a dll.
Returns a handle or nil.
Notice the dllMapping mechanism, which can be used to silently load different dlls.
This is useful, if some code has a hardcoded dll-name in it, which needs to be changed,
but you do not want or cannot recompile the methods (i.e. no source avail)

o  prepareInvoke
called before invoked.
When called the very first time, moduleHandle is nil,
and we ensure that the dll is loaded, the function address is extracted

o  prepareObjCInvoke
called before invoked

private-accessing
o  name: functionNameOrVirtualIndex module: aModuleName returnType: aReturnType argumentTypes: argTypes

o  owningClass

o  owningClass: aClass

o  setModuleName: aModuleName

private-invoking
o  invokeCPPVirtualFFIOn: instance withArguments: arguments

o  invokeFFIWithArguments: arguments

o  invokeFFIwithArguments: argumentsOrNilArg forInstance: 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

o  tryAgainWithAsyncSafeArguments: argumentsOrNil forInstance: 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.

testing
o  isExternalLibraryFunction
return true, if the receiver is some kind of externalLibrary function;
true is returned here



ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Thu, 28 Mar 2024 14:51:35 GMT