Lisp HUG Maillist Archive

Objc interface: NSError reference arguments

What is the proper way to invoke an Objective-C method that takes an NSError argument by reference if I want to check the NSError after the call completes?

Suppose, for example, that I want to invoke a method with a signature likethis:
initWithName:(NSString *)name
  config: (SomeConfigurationClass*)config
  error:(NSError *)error;

The Lispworks manual shows how to pass arguments by reference like this:

(defun get-result (object)
  (fli:with-dynamic-foreign-objects ((result-value :int))
    (objc:invoke object "getValueInto:" result-value)
    (fli:dereference result-value)))

What type should the argument error take?

NSError is a class; the Objective-C manual says that the type named objc:objc-object-pointer represents instances of Objective-C classes. That suggests that I should be using something like

  (fli:with-dynamic-foreign-objects ((err :objc-object-pointer))
    (objc:invoke object "initWithName:config:error" my-name my-config err)
    (fli:dereference err)))

...but the Lispworks compiler complains that objc-object-pointer is an illegal foreign type (I've tried writing the name various ways). 

Using :pointer yields 

Illegal instruction(4) [code 0] at 7FFF7DF731C2
        Foreign code offset #x17 from symbol "_os_unfair_lock_recursive_abort"
        module "/usr/lib/system/libsystem_platform.dylib" [ #x7FFF7DF6D000 ]

The examples in the Library are no help; the Objective-C method calls that take an error argument are called with NIL for that argument, which is then ignored.

I can of course pass NIL, as the examples do, but what's the right way to invoke the method if I want to be able to check the NSError argument after the method call?

Re: Objc interface: NSError reference arguments



On 18 Sep 2019, at 14:53, mikel evins <mevins@me.com> wrote:

What is the proper way to invoke an Objective-C method that takes an NSError argument by reference if I want to check the NSError after the call completes?

Suppose, for example, that I want to invoke a method with a signature likethis:
initWithName:(NSString *)name
  config: (SomeConfigurationClass*)config
  error:(NSError *)error;


Check your API.  Usually, it’s (NSError**)error, not (NSError*)error.

So you would pass either NULL if you’re not interested in the error, or:

NSError* error=nil;
[object fooWithSomething:something error: &error]
if(error){
  handle_the_error(error);}


If you have an API with effectively (NSError*)error then the error cannot be an output parameter, but an input parameter.  
You will have to allocate an NSError instance, or obtain one from another method.


I won’t enter into the details of Lispworks specific FFI, since I use cffi in general...
-- 
__Pascal J. Bourguignon__




Re: Objc interface: NSError reference arguments

Good point; thanks.


On Sep 18, 2019, at 9:07 AM, Pascal Bourguignon <pjb@informatimago.com> wrote:



On 18 Sep 2019, at 14:53, mikel evins <mevins@me.com> wrote:

What is the proper way to invoke an Objective-C method that takes an NSError argument by reference if I want to check the NSError after the call completes?

Suppose, for example, that I want to invoke a method with a signature likethis:
initWithName:(NSString *)name
  config: (SomeConfigurationClass*)config
  error:(NSError *)error;


Check your API.  Usually, it’s (NSError**)error, not (NSError*)error.

So you would pass either NULL if you’re not interested in the error, or:

NSError* error=nil;
[object fooWithSomething:something error: &error]
if(error){
  handle_the_error(error);}


If you have an API with effectively (NSError*)error then the error cannot be an output parameter, but an input parameter.  
You will have to allocate an NSError instance, or obtain one from another method.


I won’t enter into the details of Lispworks specific FFI, since I use cffi in general...
-- 
__Pascal J. Bourguignon__





Re: Objc interface: NSError reference arguments

Unable to parse email body. Email id is 15030

Re: Objc interface: NSError reference arguments

I think you and pjb correctly identified my error. I'll proceed on that basis. If it turns out not to be true, I'll ask more questions.

Thanks!


> On Sep 18, 2019, at 9:10 AM, Martin Simmons <martin@lispworks.com> wrote:
> 
>>>>>> On Wed, 18 Sep 2019 07:53:19 -0500, mikel evins said:
>> 
>> What is the proper way to invoke an Objective-C method that takes an NSError argument by reference if I want to check the NSError after the call completes?
>> 
>> Suppose, for example, that I want to invoke a method with a signature likethis:
>> initWithName:(NSString *)name
>>  config: (SomeConfigurationClass*)config
>>  error:(NSError *)error;
> 
> Are you sure this is (NSError *)?  I would expect (NSError **) like this:
> 
> initWithName:(NSString *)name
>  config: (SomeConfigurationClass*)config
>  error:(NSError **)error;
> 
> 
>> The Lispworks manual shows how to pass arguments by reference like this:
>> 
>> (defun get-result (object)
>>   (fli:with-dynamic-foreign-objects ((result-value :int))
>>     (objc:invoke object "getValueInto:" result-value)
>>     (fli:dereference result-value)))
>> 
>> What type should the argument error take?
>> 
>> NSError is a class; the Objective-C manual says that the type named objc:objc-object-pointer represents instances of Objective-C classes. That suggests that I should be using something like
>> 
>>  (fli:with-dynamic-foreign-objects ((err :objc-object-pointer))
>>     (objc:invoke object "initWithName:config:error" my-name my-config err)
>>     (fli:dereference err)))
>> 
>> ...but the Lispworks compiler complains that objc-object-pointer is an illegal foreign type (I've tried writing the name various ways). 
> 
> It should be:
> 
> (fli:with-dynamic-foreign-objects ((err objc:objc-object-pointer))
>  (objc:invoke object "initWithName:config:error:" my-name my-config err)
>  (fli:dereference err))
> 
> This works for me with NSData dataWithContentsOfFile:options:error: at least.
> 
> 
>> 
>> Using :pointer yields 
>> 
>> Illegal instruction(4) [code 0] at 7FFF7DF731C2
>>        Foreign code offset #x17 from symbol "_os_unfair_lock_recursive_abort"
>>        module "/usr/lib/system/libsystem_platform.dylib" [ #x7FFF7DF6D000 ]
> 
> I would expect :pointer to work too.
> 
> Do you get this error inside initWithName:config:error: or after it has
> returned?  You might need to check the return value of objc:invoke first,
> before using the value of (fli:dereference err).
> 
> -- 
> Martin Simmons
> LispWorks Ltd
> http://www.lispworks.com/
> 
> _______________________________________________
> Lisp Hug - the mailing list for LispWorks users
> lisp-hug@lispworks.com
> http://www.lispworks.com/support/lisp-hug.html


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Updated at: 2020-12-10 08:29 UTC