2017-02-14 08:29:30 +00:00
|
|
|
class _FFI(Object) from 'ffi'
|
2017-01-10 10:50:26 +00:00
|
|
|
{
|
2017-03-30 14:59:55 +00:00
|
|
|
method(#primitive) open(name).
|
2017-03-31 14:21:22 +00:00
|
|
|
method(#primitive) close.
|
2017-03-30 14:59:55 +00:00
|
|
|
method(#primitive) getsym(name).
|
|
|
|
|
2019-06-19 12:38:09 +00:00
|
|
|
/* TODO: make call variadic? method(#primitive,#variadic) call (func, sig). */
|
2017-03-30 14:59:55 +00:00
|
|
|
method(#primitive) call(func, sig, args).
|
2017-01-10 10:50:26 +00:00
|
|
|
}
|
|
|
|
|
2018-12-22 08:37:18 +00:00
|
|
|
class FFIException(Exception)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-01-09 13:41:11 +00:00
|
|
|
class FFI(Object)
|
|
|
|
{
|
2017-04-19 16:46:44 +00:00
|
|
|
var name, ffi, funcs.
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2019-09-04 15:06:24 +00:00
|
|
|
/*
|
|
|
|
pooldic Type
|
|
|
|
{
|
2019-09-30 08:46:50 +00:00
|
|
|
UINT8 := 1,
|
|
|
|
UINT16 := 2,
|
|
|
|
UINT32 := 3,
|
|
|
|
UINT64 := 4
|
2019-09-04 15:06:24 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
2019-09-30 08:46:50 +00:00
|
|
|
const UINT8 := 1,
|
|
|
|
const UINT16 := 2
|
2019-09-04 15:06:24 +00:00
|
|
|
*/
|
|
|
|
|
2017-01-09 13:41:11 +00:00
|
|
|
method(#class) new: aString
|
|
|
|
{
|
|
|
|
^self new open: aString.
|
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
method initialize
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
|
|
|
self.funcs := Dictionary new.
|
2017-01-10 10:50:26 +00:00
|
|
|
self.ffi := _FFI new.
|
2019-08-12 15:54:09 +00:00
|
|
|
//self addToBeFinalized.
|
2017-01-10 10:50:26 +00:00
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2019-08-12 15:54:09 +00:00
|
|
|
/*method finalize
|
|
|
|
{
|
|
|
|
self close
|
|
|
|
}*/
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
method open: name
|
|
|
|
{
|
|
|
|
| x |
|
|
|
|
self.funcs removeAllKeys.
|
|
|
|
self.name := name.
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-03-30 14:59:55 +00:00
|
|
|
x := self.ffi open(name).
|
2019-08-10 04:08:49 +00:00
|
|
|
//(x isError) ifTrue: [^x].
|
2019-08-10 17:36:34 +00:00
|
|
|
if (x isError) { FFIException signal: ('Unable to open %O' strfmt(name)) }.
|
2017-01-09 13:41:11 +00:00
|
|
|
|
|
|
|
^self.
|
|
|
|
}
|
|
|
|
|
|
|
|
method close
|
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
self.ffi close.
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
method call: name signature: sig arguments: args
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2018-12-22 08:37:18 +00:00
|
|
|
| f rc |
|
2018-12-20 16:08:56 +00:00
|
|
|
|
2019-09-04 15:06:24 +00:00
|
|
|
//self.Type.UINT8 dump.
|
|
|
|
//#[ self.Type.UINT8, FFI.Type.UINT16 ] dump.
|
|
|
|
|
2019-06-19 12:38:09 +00:00
|
|
|
/* f := self.funcs at: name ifAbsent: [
|
2018-12-20 16:08:56 +00:00
|
|
|
f := self.ffi getsym(name).
|
2019-08-10 17:36:34 +00:00
|
|
|
if (f isError) { FFIException signal: ('Unable to find %O' strfmt(name)) }.
|
2018-12-20 16:08:56 +00:00
|
|
|
self.funcs at: name put: f.
|
2019-06-27 06:29:09 +00:00
|
|
|
f. // need this as at:put: returns an association
|
2019-06-19 12:38:09 +00:00
|
|
|
]. */
|
2018-12-20 16:08:56 +00:00
|
|
|
|
|
|
|
f := self.funcs at: name ifAbsent: [ nil ].
|
|
|
|
if (f isNil)
|
|
|
|
{
|
2017-03-30 14:59:55 +00:00
|
|
|
f := self.ffi getsym(name).
|
2019-08-10 17:36:34 +00:00
|
|
|
if (f isError) { FFIException signal: ('Unable to find %O' strfmt(name)) }.
|
2017-01-10 10:50:26 +00:00
|
|
|
self.funcs at: name put: f.
|
2018-12-20 16:08:56 +00:00
|
|
|
}.
|
2017-01-10 13:56:19 +00:00
|
|
|
|
2018-12-22 08:37:18 +00:00
|
|
|
rc := self.ffi call(f, sig, args).
|
2019-09-04 15:06:24 +00:00
|
|
|
if (rc isError) { FFIException signal: ('Unable to call %O - %O' strfmt(name, rc)) }.
|
2019-04-07 17:54:44 +00:00
|
|
|
|
|
|
|
^rc.
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
}
|