Calling an non-DLL external function

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Calling an non-DLL external function

Udo Schneider
Is there a possibility to call an external function when just the
pointer to the function is known?

Thanks,

Udo


Reply | Threaded
Open this post in threaded view
|

Re: Calling an non-DLL external function

Blair McGlashan
Udo

You wrote in message news:[hidden email]...
> Is there a possibility to call an external function when just the
> pointer to the function is known?

Indeed. Its easiest if you know the prototype of the method in advance, and
slightly harder if you want to construct the call completely dynamically.
See the attached for some examples.

Regards

Blair

------------
Object subclass: #FunctionPointerEg
 instanceVariableNames: ''
 classVariableNames: ''
 poolDictionaries: ''
 classInstanceVariableNames: ''!
FunctionPointerEg guid: (GUID fromString:
'{67561145-D803-4B5E-9B96-9175EFCB4F48}')!
FunctionPointerEg comment: 'Invoking a function at a known address -
function prototype statically known.

 FunctionPointerEg new example1

Same again, but copying the method in case we want to call the same function
at multiple addresses:

 FunctionPointerEg new example2

Same again but dynamically constructed external call method (built with the
compiler).

 FunctionPointerEg new example3

Other dynamic techniques would be to choose an existing ExternalMethod to
use as a template, then modify a copy of it to create the desired function
description, or building an ExternalMethod entirely from scratch. These are
left as an exercise for the reader.
'!
!FunctionPointerEg categoriesForClass: !Unclassified! !
!FunctionPointerEg methodsFor!

beep: anInteger dwDuration: dwDuration
 <stdcall: bool Beep dword dword>
 ^self invalidCall!

example1
 | method |
 method := (self class compiledMethodAt: #beep:dwDuration:).
 method descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
getProcAddress: 'Beep').

 300 to: 600 by: 100 do: [:i | self beep: i dwDuration: 100]
!

example2
 | method |
 method := (self class compiledMethodAt: #beep:dwDuration:) deepCopy.
 method descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
getProcAddress: 'Beep').

 600 to: 300 by: -100 do: [:i | self beep: i dwDuration: 100]
!

example3
 "The easiest way to build an ExternalMethod dynamically is to get the
compiler to do it"
 | methodSource method |

 "Somehow we've constructed this string based on information we have about
the
 number and types of the arguments, etc"
 methodSource := 'i: i j: j <stdcall: bool _ dword dword>'.

 method := Compiler compile: methodSource in: Object.
 "Set the function pointer"
 method descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
getProcAddress: 'Beep').

 (300 to: 600 by: 100), (600 to: 300 by: -100) do: [:i | method value: self
withArguments: (Array with: i with: 100)]
!

initialize
 | call |
 call := (self class compiledMethodAt: #beep:dwDuration:).
 call descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
getProcAddress: 'Beep').
! !
!FunctionPointerEg categoriesFor:
#beep:dwDuration:!*-primitives!*-unclassified!public! !
!FunctionPointerEg categoriesFor: #example1!examples!public! !
!FunctionPointerEg categoriesFor: #example2!examples!public! !
!FunctionPointerEg categoriesFor: #example3!examples!public! !
!FunctionPointerEg categoriesFor: #initialize!initializing!public! !

!FunctionPointerEg class methodsFor!

new
 ^super new initialize! !
!FunctionPointerEg class categoriesFor: #new!instance creation!public! !


Reply | Threaded
Open this post in threaded view
|

Re: Calling an non-DLL external function

Udo Schneider
Blair,

thank you very much. This explains a lot of the exteral calling mechanisms for
me.

Thanks,

Udo


Blair McGlashan wrote:

> Udo
>
> You wrote in message news:[hidden email]...
> > Is there a possibility to call an external function when just the
> > pointer to the function is known?
>
> Indeed. Its easiest if you know the prototype of the method in advance, and
> slightly harder if you want to construct the call completely dynamically.
> See the attached for some examples.
>
> Regards
>
> Blair
>
> ------------
> Object subclass: #FunctionPointerEg
>  instanceVariableNames: ''
>  classVariableNames: ''
>  poolDictionaries: ''
>  classInstanceVariableNames: ''!
> FunctionPointerEg guid: (GUID fromString:
> '{67561145-D803-4B5E-9B96-9175EFCB4F48}')!
> FunctionPointerEg comment: 'Invoking a function at a known address -
> function prototype statically known.
>
>  FunctionPointerEg new example1
>
> Same again, but copying the method in case we want to call the same function
> at multiple addresses:
>
>  FunctionPointerEg new example2
>
> Same again but dynamically constructed external call method (built with the
> compiler).
>
>  FunctionPointerEg new example3
>
> Other dynamic techniques would be to choose an existing ExternalMethod to
> use as a template, then modify a copy of it to create the desired function
> description, or building an ExternalMethod entirely from scratch. These are
> left as an exercise for the reader.
> '!
> !FunctionPointerEg categoriesForClass: !Unclassified! !
> !FunctionPointerEg methodsFor!
>
> beep: anInteger dwDuration: dwDuration
>  <stdcall: bool Beep dword dword>
>  ^self invalidCall!
>
> example1
>  | method |
>  method := (self class compiledMethodAt: #beep:dwDuration:).
>  method descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
> getProcAddress: 'Beep').
>
>  300 to: 600 by: 100 do: [:i | self beep: i dwDuration: 100]
> !
>
> example2
>  | method |
>  method := (self class compiledMethodAt: #beep:dwDuration:) deepCopy.
>  method descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
> getProcAddress: 'Beep').
>
>  600 to: 300 by: -100 do: [:i | self beep: i dwDuration: 100]
> !
>
> example3
>  "The easiest way to build an ExternalMethod dynamically is to get the
> compiler to do it"
>  | methodSource method |
>
>  "Somehow we've constructed this string based on information we have about
> the
>  number and types of the arguments, etc"
>  methodSource := 'i: i j: j <stdcall: bool _ dword dword>'.
>
>  method := Compiler compile: methodSource in: Object.
>  "Set the function pointer"
>  method descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
> getProcAddress: 'Beep').
>
>  (300 to: 600 by: 100), (600 to: 300 by: -100) do: [:i | method value: self
> withArguments: (Array with: i with: 100)]
> !
>
> initialize
>  | call |
>  call := (self class compiledMethodAt: #beep:dwDuration:).
>  call descriptorLiteral dwordAtOffset: 0 put: (KernelLibrary default
> getProcAddress: 'Beep').
> ! !
> !FunctionPointerEg categoriesFor:
> #beep:dwDuration:!*-primitives!*-unclassified!public! !
> !FunctionPointerEg categoriesFor: #example1!examples!public! !
> !FunctionPointerEg categoriesFor: #example2!examples!public! !
> !FunctionPointerEg categoriesFor: #example3!examples!public! !
> !FunctionPointerEg categoriesFor: #initialize!initializing!public! !
>
> !FunctionPointerEg class methodsFor!
>
> new
>  ^super new initialize! !
> !FunctionPointerEg class categoriesFor: #new!instance creation!public! !