Is there a possibility to call an external function when just the
pointer to the function is known? Thanks, Udo |
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! ! |
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! ! |
Free forum by Nabble | Edit this page |