2014-11-16 19:11 GMT+01:00 Max Leske <[email protected]>:
>
> On 15.11.2014, at 22:28, Igor Stasenko <[email protected]> wrote:
>
>
>
> On 15 November 2014 15:53, Max Leske <[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!)
>
> 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.
>
>
>