<div dir="ltr"><div>I'm still struggling with FFI.<br>And more specifically ExternalType and compiledSpec.<br><br>The headerWord of the compiledSpec is composed of those bits:<br>    atomicTypeCode - atomic-pointer-struct bits - byteSize<br>     (4 bits used/8 high bits) - (3 bits used/8 bits) - (16 low bits)<br><br>So, the atomic type short is encoded with atomicType=5, atomicBit(4),size=2:<br>    ExternalType short compiledSpec first hex -> '16r5040002'<br><br>and short *, is same with pointerBit(2) set, and size=pointer size (4 on 32bits)<br>    ExternalType short asPointerType compiledSpec first hex -> '16r5060004'<br><br>Note that I had to correct the pointer size for 64 bits in FFI-Kernel-nice.52!!!<br></div><div>(I corrected the same bug in the plugin a few days back, so it's better to match).<br></div><div><br>Now what happens with an ExternalStructure? it has the structureBit(1) set:<br>    (ExternalType structTypeNamed: #FFITestPoint2) compiledSpec first hex -> '16r10008'<br><br>OK, and what about FFITestPoint2 *?<br>    (ExternalType structTypeNamed: #FFITestPoint2) asPointerType compiledSpec first hex -> '16r20004'<br><br>Ah, surprising, it has the pointerBit(2) set, but no structureBit nor atomicBit.<br>My own expectation would be 16r30004...<br>So I thought that this could have been on purpose to match void *, but no:<br>    ExternalType void asPointerType compiledSpec first hex -> '16r60004'<br><br>And what about type aliases?<br>    (ExternalType structTypeNamed: #Win32Handle) compiledSpec first hex -> '16r6040004'<br><br>Since it is an alias for ulong (understand uint32_t), we get the same compiledSpec<br>    ExternalType ulong compiledSpec first hex -> '16r6040004'<br><br>OK, and what about a Win32Handle* (if it ever makes sense)<br>    (ExternalType structTypeNamed: #Win32Handle) asPointerType compiledSpec first hex -> '16r20004'<br>Ouch ! Doubly surprising, it's like any other structure!<br>If I want to alias a type, is the pointer to the alias really going to work as expected???<br>    ExternalType ulong asPointerType compiledSpec first hex -> '16r6060004'<br><br>And now, let's insepct some code:<br>isStructureType<br>    "Return true if the receiver represents a structure type"<br>    ^self headerWord anyMask: FFIFlagStructure<br><br>isPointerType<br>    "Return true if the receiver represents a pointer type"<br>    ^self isStructureType not and:[self headerWord anyMask: FFIFlagPointer]<br><br>embeddedSpecWithSize: typeSize<br>    "Return a compiled spec for embedding in a new compiled spec."<br>    | spec header |<br>    spec := self compiledSpec copy.<br>    header := spec at: 1.<br>    header := (header bitAnd: FFIStructSizeMask bitInvert32) bitOr: typeSize.<br>    spec at: 1 put: header.<br>    (self isStructureType and:[self isPointerType not])<br>        ifTrue:[spec := spec copyWith: self class structureSpec].<br>    ^spec<br><br>I absolutely do not understand such code.<br>1- (self isStructureType and:[self isPointerType not]) is always false with the above definitions!!!<br>2- If it were not, I don't understand the intention to follow embedded structures (nested structures) specs with a void structure spec 16r10000, nor where it is used...<br><br>And yet another obscure and questionable choice: alias to a pointer:<br><br>compileAlias: spec withAccessors: aBool<br>    ...snip...<br>    isPointerField<br>        ifTrue:[compiledSpec := WordArray with:<br>                    (ExternalType structureSpec bitOr: ExternalType pointerSpec)]<br>        ifFalse:[compiledSpec := externalType compiledSpec].<br><br>So finally, the combination pointerBit(2)+structureBit(1) is used in the system, not exactly where I expected, but when a type is an alias to a pointer (but remember, not necessarily a pointer to a structure).<br>    (ExternalType structTypeNamed: #MacPixPatPtr) compiledSpec first hex -> '16r30004'<br><br>Completely brainfuck: the least I expect from such niceties is looonng and well detailed explanation. Where is the F... manual?<br><br></div>With this ability of human brain to perceive order in perfectly random patterns, I'm just beginning to see the light: for some reasons, we want an alias to a pointer not being handled as a pointer, thus the special use case for pointerBit+structureBit (16r30004) and thus the bizarre definition of isPointerType... Now what are those reasons?<br><div><br>I'm in a situation where I have plenty of very logical FFI declarations that just don't work.<br>I thought I had understood enough of FFI to propose some corrections to the plugin.<br>But now, I'm not even sure. And maintaining backward compatibility with obscure undocumented features is going to be very challenging...<br><br>Sometimes, the Pharo style scorched earth policy is very tempting ;)<br></div><div>Or I can just fork, implement the missing multiple-pointer-level spec, the missing array spec, the missing union spec, correct the 64bits slips, handle the alignment... <br></div><div>Before inventing my own square wheel, I will have another look at Esteban's UFFI, he has been there before me.<br></div><div><br>Nicolas<br><br><br><br></div></div>