Lua-Objective-C-Bridge icon indicating copy to clipboard operation
Lua-Objective-C-Bridge copied to clipboard

bool values are not read back into Lua from Obj-c method calls

Open DJHoltkamp opened this issue 9 years ago • 6 comments

When calling an Objective-c's class method which returns a bool, regardless of what I return, the value read within lua always appears to be 1.

UPDATE: Doing additional tests are showing that the failure condition does not occur with a simple method. I will continue to refine and give exact failure conditions shortly

DJHoltkamp avatar Mar 26 '15 20:03 DJHoltkamp

It would appear that the signature of the method being called affects the ability to read the return type. A bool returning objective-c method seems to correctly get its return value assigned in the lua interpreter, as well as a method with the signature: -(bool)returnBool:(bool)junk

However, if I change signature to be: -(bool)returnBool:(NSString*)junk

then the value returned is always 1.

Here is how I am calling the method from Obj-c: collection_manager = bridge:wrap(class.Collection)("sharedCollection") local bool_test = collection_manager("returnBool:", "string")

DJHoltkamp avatar Mar 26 '15 20:03 DJHoltkamp

Hmm... The return value is encoded here: https://github.com/torus/Lua-Objective-C-Bridge/blob/master/LuaBridge.m#L371

A Boolean value is converted to NSNumber with numberWithBool:. Can you try to add a break point on this line and see what's happening?

Type Encodings shows how method signature is encoded.

torus avatar Mar 29 '15 04:03 torus

My line numbers don't match so I should probably pull again (and should have before opening this, so apologies). Assuming this isn't a recently fixed bug, it would appear to be a pointer error. For some reason, with the NSString as a method parameter, the x value is actually the pointer address.

When printing out print *((bool *)buffer)

I get (bool) $0 = false

which is correct

however: print x (int) $1 = -1154213888

With the method signature changed back to not include the NSString, I get:

(lldb) print *((bool *)buffer) (bool) $0 = false (lldb) print x (int) $1 = 0

DJHoltkamp avatar Mar 29 '15 04:03 DJHoltkamp

Ok, I realize now that it should be noted that I am running this on iOS. I believe this could have a fairly big impact and I believe is the cause of the problem (at least possibly).

The following seemed to clear it up for me: case 'B': // A C++ bool or a C99 _Bool { CNVBUF(BOOL); [stack addObject:[NSNumber numberWithBool:x]]; }

If we look at the definition of a bool /// Type to represent a boolean value. #if !defined(OBJC_HIDE_64) && TARGET_OS_IPHONE && LP64 typedef bool BOOL; #else typedef signed char BOOL; // BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" // even if -funsigned-char is used. #endif

So sometimes is a char and sometimes an int.

DJHoltkamp avatar Mar 29 '15 04:03 DJHoltkamp

Oh...

torus avatar Mar 29 '15 05:03 torus

Ok, so here is what I think may be happening after digesting this:

  • You are casting a BOOL pointer to an int which is grabbing 4 bytes signed. On iOS, the pointer is actually point to one byte so you have 3 more bytes of the stack. The reason I see the changes is that you probably have some non 0 bits on the stack when there is an NSString on there too which we are grabbing part of which is why I alway get true when having the NSString as a method parameter. I believe by fix above would alleviate this issue on iOS by correctly choosing between 1 and 4 bytes.

DJHoltkamp avatar Mar 29 '15 05:03 DJHoltkamp