I'd like to pass an UninterpretedBytes to an external library, say something like this
MyLibrary>>foo: buf len: len
<C: int foo(void *buf,unsigned int len)>
MyApplication>>test
buffer := UninterpretedBytes new: 4.
^MyLibrary new foo: buffer len: buffer size.
But this fails in CPointerType>>coerceForArgument:anObject
.
I know that I could use buffer gcCopyToHeap
but I don't want to.
I want to handle an object in Smalltalk memory with Smalltalk 1-based address and no extra copy nor any other complication.
I find the last lines of CPointerType>>coerceForArgument:anObject
suspiscious:
(anObject isString
or: [self isOopRef and: [anObject class isBits and: [anObject class isVariable]]])
ifTrue: [^anObject].
self isOopRef
means that the CPointerType has been declared as _oopref *
.
If I cheat and declare:
MyLibrary>>foo: buf len: len
<C: int foo(_oopref *buf,unsigned int len)>
then MyApplication new test
works as expected, but I don't want to cheat, the prototypes are extracted automatically from C headers and I don't want to patch them manually.
self isOopRef
semantically means is a reference to an Object Oriented Pointer.
Every Object can be viewed as an Object Oriented Pointer and can thus be passed by reference to such _oopref *
, except immediate objects like SmallInteger SmallDouble Character. There is a guard above in code to check for the case when anObject isImmediate
, so at this stage, anObject
is definitely an oop.
Such _oopref could be manipulated from within the external C-code, for example thru some Object Engine function oe*(), and this is not limited to arrays of bytes/words/double words!
The guard and: [anObject class isBits and: [anObject class isVariable]]
thus makes no sense.
If I modify the last lines of CPointerType>>coerceForArgument:anObject
into:
(anObject isString
or: [self isOopRef or: [anObject class isBits and: [anObject class isVariable]]])
ifTrue: [^anObject].
Then MyApplication new test
works like a charm.
Wasn't it the real intention? Pass either any kind of non immediate object if the prototype specifies a pointer to an oop, or pass a reference to an array of bytes/words/...