On 17.11.2014, at 00:32, Nicolai Hess <nicolaihess@web.de> wrote:



2014-11-16 19:11 GMT+01:00 Max Leske <maxleske@gmail.com>:

On 15.11.2014, at 22:28, Igor Stasenko <siguctua@gmail.com> wrote:



On 15 November 2014 15:53, Max Leske <maxleske@gmail.com> 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.