FFI: FFI-Callbacks-mt.19.mcz

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

FFI: FFI-Callbacks-mt.19.mcz

commits-2
Marcel Taeumel uploaded a new version of FFI-Callbacks to project FFI:
http://source.squeak.org/FFI/FFI-Callbacks-mt.19.mcz

==================== Summary ====================

Name: FFI-Callbacks-mt.19
Author: mt
Time: 26 May 2021, 6:18:08.303788 pm
UUID: 07f5dc26-d1f1-6549-932e-42693011e920
Ancestors: FFI-Callbacks-mt.18

Adds callback-convenience for bsearch and qsort, which also serve as commentary and examples for other callbacks. Complements FFI-Kernel-mt.171.

Moves qsort examples to new FFI-CallbacksTests package.

=============== Diff against FFI-Callbacks-mt.18 ===============

Item was added:
+ ----- Method: BlockClosure>>signature: (in category '*FFI-Callbacks') -----
+ signature: signature
+
+ ^ FFICallback
+ signature: signature
+ block: self!

Item was added:
+ ----- Method: CStandardLibrary>>bsearch:in:compare: (in category '*FFI-Callbacks') -----
+ bsearch: key in: array compare: block
+
+ | result |
+ result := self
+ bsearch: key
+ with: array
+ with: array size
+ with: array contentType byteSize
+ with: (self compare: array contentType through: block) thunk.
+ result
+ setContentType: array contentType;
+ setSize: 1.
+ ^ result!

Item was added:
+ ----- Method: CStandardLibrary>>compare:through: (in category '*FFI-Callbacks') -----
+ compare: contentType through: evaluable
+ "Answers a callback for comparing the given contentType through the given evaluable, i.e., messages sends or blocks. Supports pointer types as contentType."
+
+ <callback: int32_t (*)(const void*, const void*)>
+
+ | argType signature |
+ self assert: [evaluable numArgs = 2].
+
+ argType := contentType isPointerType
+ ifTrue: [(contentType asArrayType: nil)]
+ ifFalse: [contentType].
+
+ signature := ((thisContext method pragmaAt: #callback:) argumentAt: 1) copy.
+ signature at: 2 put: argType asPointerType.
+ signature at: 3 put: argType asPointerType.
+
+ ^ evaluable signature: signature!

Item was added:
+ ----- Method: CStandardLibrary>>qsort:compare: (in category '*FFI-Callbacks') -----
+ qsort: array compare: block
+
+ ^ self
+ qsort: array
+ with: array size
+ with: array contentType byteSize
+ with: (self compare: array contentType through: block) thunk!

Item was removed:
- ----- Method: FFICallback class>>cdeclQsort:with:with:with: (in category 'examples') -----
- cdeclQsort: values with: number with: width with: callback
-
- <cdecl: void 'qsort' (void* size_t size_t void*) module: 'msvcrt.dll'>
- ^ self externalCallFailed!

Item was removed:
- ----- Method: FFICallback class>>exampleCqsort01 (in category 'examples') -----
- exampleCqsort01
- "Call the libc qsort function (which requires a callback)."
- "FFICallback exampleCqsort01"
- "(Time millisecondsToRun: [100 timesRepeat: [FFICallback exampleCqsort]]) / 100.0"
-
- | type cb rand nElements values orig sort libcName knownLibcNames fn |
-
- knownLibcNames := #('libobjc.dylib' 'libgcc_s.1.dylib' 'libc.dylib' 'libc.so.6' 'libc.so' 'msvcrt.dll').
- libcName := Project uiManager chooseFrom: knownLibcNames title: 'Choose your libc'.
- libcName = 0 ifTrue: [^ self].
- libcName := knownLibcNames at: libcName.
-
- rand := Random new.
- type := ExternalType double.
- nElements := 10.
- values := type allocateExternal: nElements.
- "Initialize external data and set size for enumeration."
- 1 to: nElements do: [:i| values at: i put: rand next].
- "Fetch a local copy of the external data."
- orig := values copy.
-
- "Construct the callback structure."
- cb := FFICallback
- signature: '<callback: int (*)(double* double*)>'
- "signature: #(int 'double*' 'double*')"
- block: [ :arg1 :arg2 |
- | a  b |
- a := arg1.
- b := arg2.
- (a - b) sign].
-
- "void qsort( void *base, size_t number, size_t width, int (__cdecl *compare )(const void *, const void *) );"
- fn := ExternalLibraryFunction
- name: 'qsort' module: libcName
- callType: ExternalLibraryFunction callTypeCDecl
- returnType: ExternalType void
- argumentTypes: (ExternalType lookupTypes: #('void*' size_t size_t 'void*')).
-
- "Invoke!!"
- fn
- invokeWith: values "getHandle"
- with: nElements
- with: type byteSize
- with: cb thunk "getHandle".
-
- sort := values collect: [:each | each].
- values free.
- ^orig -> sort!

Item was removed:
- ----- Method: FFICallback class>>exampleCqsort02 (in category 'examples') -----
- exampleCqsort02
- "Call the libc qsort function (which requires a callback)."
- "
- FFICallback exampleCqsort02
- "
- "(Time millisecondsToRun: [100 timesRepeat: [FFICallback exampleCqsort]]) / 100.0"
-
- | type rand nElements sizeofDouble values orig sort |
-
- rand := Random new.
- type := ExternalType double.
- sizeofDouble := type byteSize.
- nElements := 10.
- values := type allocateExternal: nElements.
- "Initialize external data and set size for enumeration."
- 1 to: nElements do: [:i| values at: i put: rand next].
-
- "Fetch a local copy of the external data."
- orig := values copy.
-
- "Invoke!!"
- self
- qsort: values  with: values size with: values contentType byteSize
- with:  [ :arg1 :arg2 |
- | a  b |
- a := arg1.
- b := arg2.
- (a - b) sign].
-
- sort := values copy.
- values free.
- ^orig -> sort!

Item was removed:
- ----- Method: FFICallback class>>exampleCqsort03 (in category 'examples') -----
- exampleCqsort03
- "Call the libc qsort function (which requires a callback)."
- "
- FFICallback exampleCqsort03
- "
- "(Time millisecondsToRun: [100 timesRepeat: [FFICallback exampleCqsort]]) / 100.0"
-
- | type rand nElements values orig sort cb |
-
- rand := Random new.
- type := ExternalType double.
- nElements := 10.
- values := type allocateExternal: nElements.
- "Initialize external data and set size for enumeration."
- 1 to: nElements do: [:i| values at: i put: rand next].
-
- "Fetch a local copy of the external data."
- orig := values copy.
-
- "Construct the callback structure."
- cb := FFICallback
- signature: '<callback: int (*)(double* double*)>'
- "signature: #(int 'double*' 'double*')"
- block: [ :arg1 :arg2 |
- | a  b |
- a := arg1.
- b := arg2.
- (a - b) sign].
-
-
- "Invoke!!"
- self
- cdeclQsort: values  with: values size with: values contentType byteSize
- with: cb thunk.
-
- sort := values collect: [:each | each].
- values free.
- ^orig -> sort!

Item was removed:
- ----- Method: FFICallback class>>exampleCqsort04 (in category 'examples') -----
- exampleCqsort04
- "
- FFICallback exampleCqsort04
- "
-
- | type in out fn cb |
- type := ExternalType int32_t.
- in := type allocateExternal: 10.
- 1 to: in size do: [:each |
- in at: each put: 100 atRandom].
-
- cb := FFICallback
- signature: '<callback: int (*)(int32_t* int32_t*)>'
- "signature: #(int 'double*' 'double*')"
- block: [ :arg1 :arg2 |
- | a  b |
- a := arg1.
- b := arg2.
- (a - b) sign].
-
- fn := ExternalLibraryFunction
- name: 'qsort' module: 'msvcrt.dll'
- callType: ExternalLibraryFunction callTypeCDecl
- returnType: ExternalType void
- argumentTypes: (ExternalType lookupTypes: #('void*' size_t size_t 'void*')).
-
- "Invoke!!"
- [fn
- invokeWith: in "getHandle"
- with: in size
- with: in contentType byteSize
- with: cb thunk "getHandle"]
- ifCurtailed: [in free].
-
- out := in copy.
- in free.
- ^ out!

Item was removed:
- ----- Method: FFICallback class>>qsort:with:with:with: (in category 'examples') -----
- qsort: values with: number with: width with: block
- "Indirection to define the signature for the provided block."
- <callback: int (*)(double* double*)>
-
- | callback |
- callback := FFICallback
- signature: ((thisContext method pragmaAt: #callback:) argumentAt: 1)
- block: block.
-
- ^ self cdeclQsort: values with: number with: width with: callback thunk!