Replacement for descriptionForInstanceMethod:

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Replacement for descriptionForInstanceMethod:

Andreas Höschler
Hi all,

I used to do stuff like so

   struct objc_method_description *methodDescription = NULL;
   methodDescription = [_protocol descriptionForInstanceMethod:aSelector];
   if (methodDescription == NULL) methodDescription = [_protocol descriptionForClassMethod:aSelector];
   if (methodDescription != NULL) types = methodDescription->types;

using my ancient GNustep tree. This no longer works since [Protocol descriptionForInstanceMethod:] got deprecated and no longer available. I tried to replace this with (complete test code):

@protocol TestProtocol

- (void)doIt;

@end

Protocol * _protocol = @protocol(TestProtocol);
SEL aSelector = @selector(doIt);
struct objc_method_description _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, YES);
if (_methodDescription.name == NULL) _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, NO);
NSLog(@"_methodDescription.name %@", NSStringFromSelector(_methodDescription.name));

but always get

2018-05-08 17:43:02.800 AppbaseClient[37957:168060] _methodDescription.name (null)

What am I doing wrong?

Thanks a lot,

 Andreas



_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: Replacement for descriptionForInstanceMethod:

Fred Kiefer
You should have a look at GSProtocolGetMethodDescriptionRecursive in Additions/GSObjCRuntime.m. I think this should be able to provide the required functionality.

Hope this helps,
Fred

> Am 08.05.2018 um 17:49 schrieb Andreas Höschler <[hidden email]>:
>
> Hi all,
>
> I used to do stuff like so
>
>    struct objc_method_description *methodDescription = NULL;
>    methodDescription = [_protocol descriptionForInstanceMethod:aSelector];
>    if (methodDescription == NULL) methodDescription = [_protocol descriptionForClassMethod:aSelector];
>    if (methodDescription != NULL) types = methodDescription->types;
>
> using my ancient GNustep tree. This no longer works since [Protocol descriptionForInstanceMethod:] got deprecated and no longer available. I tried to replace this with (complete test code):
>
> @protocol TestProtocol
>
> - (void)doIt;
>
> @end
>
> Protocol * _protocol = @protocol(TestProtocol);
> SEL aSelector = @selector(doIt);
> struct objc_method_description _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, YES);
> if (_methodDescription.name == NULL) _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, NO);
> NSLog(@"_methodDescription.name %@", NSStringFromSelector(_methodDescription.name));
>
> but always get
>
> 2018-05-08 17:43:02.800 AppbaseClient[37957:168060] _methodDescription.name (null)
>
> What am I doing wrong?
>
> Thanks a lot,
>
>  Andreas
>
>
> _______________________________________________
> Discuss-gnustep mailing list
> [hidden email]
> https://lists.gnu.org/mailman/listinfo/discuss-gnustep


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: Replacement for descriptionForInstanceMethod:

Andreas Höschler
Hi Fred,

You should have a look at GSProtocolGetMethodDescriptionRecursive in Additions/GSObjCRuntime.m. I think this should be able to provide the required functionality.

Thanks a lot. I do

         NSMethodSignature *objcSignature = nil;
         #ifdef __APPLE__
           {
            struct objc_method_description *methodDescription = NULL;
            methodDescription = [_protocol descriptionForInstanceMethod:aSelector];
            if (methodDescription == NULL) methodDescription = [_protocol descriptionForClassMethod:aSelector];
            if (methodDescription != NULL) types = methodDescription->types;
           }
         #else
           {
            struct objc_method_description desc;
            desc = GSProtocolGetMethodDescriptionRecursive(_protocol, aSelector, YES, YES);
            if (desc.name == NULL && desc.types == NULL)
              {
               desc = GSProtocolGetMethodDescriptionRecursive(_protocol, aSelector, YES, NO);
              }
            types = desc.types;
           }
         #endif
         if (types) objcSignature = [NSMethodSignature signatureWithObjCTypes:types];

now. The Apple part works on Macs and with my ancient GNUstep tree. I do not know yet, whether the non-Apple part works on Ubuntu (current GNUstep) but will try once the SIGSEGV problem is figured out. :-)

It's a little surprising to me why

Protocol * _protocol = @protocol(TestProtocol);
SEL aSelector = @selector(doIt);
struct objc_method_description _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, YES);
if (_methodDescription.name == NULL) _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, NO);
NSLog(@"_methodDescription.name %@", NSStringFromSelector(_methodDescription.name));

does not work on Apple as I understood this was the recommended way to do it now!? But it simply does not work, therefore reverting back back to the deprecated approach (deprecated descriptionForInstanceMethod: method of Protocol).

Thanks so much,

 Andreas





_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: Replacement for descriptionForInstanceMethod:

Fred Kiefer


> Am 08.05.2018 um 19:16 schrieb Andreas Höschler <[hidden email]>:
>
>
>> You should have a look at GSProtocolGetMethodDescriptionRecursive in Additions/GSObjCRuntime.m. I think this should be able to provide the required functionality.
>
> Thanks a lot. I do
>
>          NSMethodSignature *objcSignature = nil;
>          #ifdef __APPLE__
>            {
>             struct objc_method_description *methodDescription = NULL;
>             methodDescription = [_protocol descriptionForInstanceMethod:aSelector];
>             if (methodDescription == NULL) methodDescription = [_protocol descriptionForClassMethod:aSelector];
>             if (methodDescription != NULL) types = methodDescription->types;
>            }
>          #else
>            {
>             struct objc_method_description desc;
>             desc = GSProtocolGetMethodDescriptionRecursive(_protocol, aSelector, YES, YES);
>             if (desc.name == NULL && desc.types == NULL)
>               {
>                desc = GSProtocolGetMethodDescriptionRecursive(_protocol, aSelector, YES, NO);
>               }
>             types = desc.types;
>            }
>          #endif
>          if (types) objcSignature = [NSMethodSignature signatureWithObjCTypes:types];
>
> now. The Apple part works on Macs and with my ancient GNUstep tree. I do not know yet, whether the non-Apple part works on Ubuntu (current GNUstep) but will try once the SIGSEGV problem is figured out. :-)
>
> It's a little surprising to me why
>
>> Protocol * _protocol = @protocol(TestProtocol);
>> SEL aSelector = @selector(doIt);
>> struct objc_method_description _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, YES);
>> if (_methodDescription.name == NULL) _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, NO);
>> NSLog(@"_methodDescription.name %@", NSStringFromSelector(_methodDescription.name));
>
> does not work on Apple as I understood this was the recommended way to do it now!? But it simply does not work, therefore reverting back back to the deprecated approach (deprecated descriptionForInstanceMethod: method of Protocol).

Most likely it isn’t working for the same reason as that code wasn’t working on GNUstep :-)
The runtime function will only check for methods defined by the protocol directly not for inherited ones. That is why the GNUstep function has „recursive“ in its name. It is checking in the ancestry of the protocol.


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: Replacement for descriptionForInstanceMethod:

Andreas Höschler
Hi Fred,

Most likely it isn’t working for the same reason as that code wasn’t working on GNUstep :-)
The runtime function will only check for methods defined by the protocol directly not for inherited ones. That is why the GNUstep function has „recursive“ in its name. It is checking in the ancestry of the protocol.

My test code was

@protocol TestProtocol

- (void)doIt;

@end

   
   Protocol *_protocol = @protocol(TestProtocol);
   SEL aSelector = @selector(doIt);
   struct objc_method_description _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, YES);
   if (_methodDescription.name == NULL) _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, NO);
   NSLog(@"_methodDescription.name %@", NSStringFromSelector(_methodDescription.name));
   
Where is the ancestry here? Isn't "doIt" defined directly in this example?

Thanks,

 Andreas


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: Replacement for descriptionForInstanceMethod:

Fred Kiefer


> Am 08.05.2018 um 19:26 schrieb Andreas Höschler <[hidden email]>:
>
>> Most likely it isn’t working for the same reason as that code wasn’t working on GNUstep :-)
>> The runtime function will only check for methods defined by the protocol directly not for inherited ones. That is why the GNUstep function has „recursive“ in its name. It is checking in the ancestry of the protocol.
>
> My test code was
>
> @protocol TestProtocol
>
> - (void)doIt;
>
> @end
>
>    
>    Protocol *_protocol = @protocol(TestProtocol);
>    SEL aSelector = @selector(doIt);
>    struct objc_method_description _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, YES);
>    if (_methodDescription.name == NULL) _methodDescription = protocol_getMethodDescription(_protocol, aSelector, NO, NO);
>    NSLog(@"_methodDescription.name %@", NSStringFromSelector(_methodDescription.name));
>    
> Where is the ancestry here? Isn't "doIt" defined directly in this example?

Here is the GNUstep code for this function:

struct objc_method_description
GSProtocolGetMethodDescriptionRecursive(Protocol *aProtocol, SEL aSel, BOOL isRequired, BOOL isInstance)
{
  struct objc_method_description desc;

  desc = protocol_getMethodDescription(aProtocol, aSel, isRequired, isInstance);
  if (desc.name == NULL && desc.types == NULL)
    {
      Protocol **list;
      unsigned int count;

      list = protocol_copyProtocolList(aProtocol, &count);
      if (list != NULL)
        {
          unsigned int i;

          for (i = 0; i < count; i++)
            {
              desc = GSProtocolGetMethodDescriptionRecursive(list[i],
                aSel, isRequired, isInstance);
              if (desc.name != NULL || desc.types != NULL)
                {
                  break;
                }
            }
          free(list);
        }
    }

  return desc;
}

As you can see, the difference must either be in the recursive call or in the isRequired parameter. You could try to set that to YES for your direct call.


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep