> On 17.11.2014, at 00:32, Nicolai Hess <[email protected]> wrote: > > > > 2014-11-16 19:11 GMT+01:00 Max Leske <[email protected] > <mailto:[email protected]>>: > >> On 15.11.2014, at 22:28, Igor Stasenko <[email protected] >> <mailto:[email protected]>> wrote: >> >> >> >> On 15 November 2014 15:53, Max Leske <[email protected] >> <mailto:[email protected]>> wrote: >> Once again I’m struggling with NativeBoost. I’m trying to use >> optCoerceNilToNull with this function: >> >> ^self call: #(LGitReturnCodeEnum git_commit_create( >> LGitId * theCommitId, >> LGitRepository repo, >> String update_ref, >> LGitSignature * theAuthor, >> LGitSignature * theCommitter, >> String message_encoding, >> String theMessage, >> LGitTree theTree, >> int parent_count, >> LGitCommit * parentsPointer)) options: #( optCoerceNilToNull ) >> >> The last argument can be NULL, per documentation, (no parents). >> LGitCommit is a subclass of NBExternalObject and apparently >> NBExternalObjctType>>pushAsPointer: does *not* use the optCoerceNilToNull >> option (the super implementation in NBExternalType>>pushAsPointer: however >> does). The upshot of course is that the call fails with “an instance of >> LGitCommit expected”. >> >> My questions: >> - The documentation says: >> >> "#optCoerceNilToNull" >> "passing nil as a pointer-type argument, converts it to C NULL “ >> >> but apparently this doesn’t apply to every pointer type. Should the >> documentation be updated? >> - Why does NBExternlObjectType not use optCoerceNilToNull? I don’t want to >> use tricks to pass null if I don’t have to. >> >> perhaps because it is not there? :) >> So, lets add it. > > Yay! :) I have zero assembly skills… I’ve tried the following but then get an > “undefined label done18” error: > > > if coerceNilToNull is set *and* the argument is indeed nil, you want to jump > over all other operations on this argument (see below). > (and if coerceNilToNull is set, and the argument is not nil, you should still > verify the class of the oop, this is missing > in your code!)
That’s true, thanks. > > > > NBExternalObject>>pushAsPointer: gen > "push a pointer to handle value" > | asm proxy oop notNil done | > > proxy := gen proxy. > asm := gen asm. > > <<<<<<<<<<<<<< new > > done := asm uniqueLabelName: 'done’. > > >>>>>>>>>>>>>>> new > > oop := gen reserveTemp. > loader emitLoad: gen to: oop. > > <<<<<<<<<<<<<< new > > "handle nils, if we care" > gen optCoerceNilToNull > ifTrue: [ > notNil := asm uniqueLabelName: 'notNil'. > proxy nilObject. > asm cmp: asm EAX with: oop; > jne: notNil; > xor: asm EAX with: asm EAX; > jmp: done; > label: notNil ] > ifFalse: [ > "we can skip class verification, if loader loads > receiver, since nothing to fear there" > loader isReceiver ifFalse: [ > self verifyClassOf: oop is: objectClass > generator: gen. > ] ]. > > >>>>>>>>>>>>>>> new > > proxy fetchPointer: (self handleIvarIndex) ofObject: oop. "handle ivar" > proxy varBytesFirstFieldOf: asm EAX. "handle value ptr" > > "done label here:" > asm label: done. > > asm push: asm EAX. > > gen releaseTemps: 1. > > >> >> - Related: there are instances where even non-pointer arguments are allowed >> to be NULL. Why does optCoerceNilToNull only work for pointer types? >> >> >> like what? Suppose the argument type is a structure, e.g >> "struct foo bar", that is non-pointer type. What in this case the NULL value >> for the structure? > > Ok, I think I understand. Are you saying that, since NULL is a macro, you > have no way of telling during runtime how NULL is defined? For a pointer it > is simply 0 or (void *) 0, but for a non pointer it depends on the context. > Is that about right? > >> >> Igor! Help! :) >> >> Cheers, >> Max >> >> >> >> >> -- >> Best regards, >> Igor Stasenko.
