Hi there,
i just uploaded new version of config - 1.8 (development),
where i introduced the new public core classs: NBExternalTypeArray.
The class provides a generic functionality for working with arrays
which elements is of foreign (C) type.
And since it is a subclass of ArrayedCollection, you can use them
naturally as any other Array(s)/Collection(s) in smalltalk.
Here the class comment:
--------------
I am abstract class which provides a convenient interface to work with
arrays which elements are values of some external (C) type.
In order to use me with concrete element type, you must create a
subclass of me and initialize element type properly.
Subclassing using public subclass:
- if you want to create a public subclass of me, then you should make
sure that in class-side #initialize method,
you add self-send #initElementType: and specify the element type name
to use. (And of course, initialize the class before attempting to
create any instances).
Subclassing with anonymous subclass:
To create an anonymous subclass of me, use #ofType: protocol, i.e.:
floatArrayClass := NBExternalTypeArray ofType: 'float'.
Please note that separate #at: / #at:put: methods will be
automatically added in each and every subclass.
Never remove them, despite they looking identical to superclass methods!
!!CAUTION!! Currently those methods do not perform any range checking
for index. So, please make sure you using sane index values (1<= index
<= size).
Also, note, that class instance variables: elementType and
elementSize, once initialized, is considered read-only.
Changing them, once you created at least a single instance of your
class may lead to funny consequences.
Arrays in external memory vs object memory:
My instances can work either with data held in object memory or in
external memory. The difference is only at instantiation time:
To create a new array in object memory, just use #new: protocol:
myArray := floatArrayClass new: 10. "create a new array with 10
floats".
To allocate a new array in external memory, use #externalNew: protocol:
myArray := floatArrayClass externalNew: 10.
..
myArray free. "and sure thing, do not forget to free external memory
after use".
To check whether array uses object memory or external memory , use
#isExternal protocol.
Also, you can convert any external address into NBExternalTypeArray
subclass instance, i.e. suppose some external function returns a
pointer (instance of NBExternalAddress):
pointer := self callSomeFunc: 1.
So, in order to access memory at given address as array of 100
elements of type 'int', you can use following:
myArray := (NBExternalTypeArray ofType: 'int') onAddress: pointer size:
100.
myArray at: 1. "read first element"
myArray at: 2 put: 50. "write second element"
myArray do: [:each | ... ] ... etc
(sure thing, in the above example, the "NBExternalTypeArray ofType:
'int' " expression is just to demonstrate the intent. It should be
replaced with some variable, which you initialize only once and use
many times, because creating an anonymous subclass each time would be
highly ineffective )
Supported protocols:
Since NBExternalTypeArray inherits from ArrayedCollection, you're
free to use any protocols defined there as well as in its
superclasses.
There's only few additions comparing to ArrayedCollection, like
#isExternal and #free .
Copying:
a #copy behavior is special for external arrays: A copy will always
use object memory, even if original used external memory.
-----------------
Now, i would really appreciate if someone could do some more serious
testing (how well it works as Collection etc), and of course do a
review and feedback :)
My nearest plans concerning NB:
- review the callbacks interface (to make it more convenient to use ,
as we discussed on this list some time ago)
- by seeing how nicely NBExternalTypeArray deals with
external/internal duality, i am now inclined to do the same for
NBExternalStructure. (Yes.. nice and simple things are not often so
obvious :) Like that, NBExternalStructure will be just a regular class
(instead of var-byte one) which will keep 'data' object which is
ByteArray for object memory allocated struct, and NBExternalAddress
for indirect reference to structure data somewhere beyond our safe
harbor ;))
- also, if time allows, i'd like to get threaded calls working. The
prototype was started by Javier almost a year ago, and we need to
finish it.
Also, we want to work together with Esteban for making Objective-C
bridge functional. This will bring us one step closer to multiple
different goals:
- native window management
- allow us to avoid extra blitting Athens -> Display -> ObjC view..
but just Athens ->Obj-C :)
- direct use of Obj-C runtime
- .. reimplement VM features in image + adding new stuff
(and sure thing, Esteban has own)
And, of course, besides of that, soon we will start working on unified
FFI interface for Pharo.
So, people will no longer need to choose between old FFI/Alien/NB,
since it will be ONE in the core functionality of a system.
P.S. i'd like to thank everyone, who helping me with development of
NB. In last couple months, i really see how your contribution helps
bringing NB to better quality levels. Even though, not all of you
risking to practice dark-assembly magic, ditching some nuances and
polishing rough corners etc is really helpful..
because i wouldn't say that i'm in a mood of polishing project right
now, because i more focused on adding missing features. :)
--
Best regards,
Igor Stasenko.