that takes returns ptr pointer argument and objective-c c pointers function-pointers

objective-c - takes - c pointer to a function



El puntero del selector Objective-C se pasa a una funciĆ³n C (3)

Tengo una estructura C que contiene un puntero a función. Ahora, he usado esta configuración dentro de C sin problemas, pero ahora estoy usando esta estructura C en Objective-C y necesito pasar el puntero a una función (o selector) que se define en la clase Objective-C.

1. Esto es lo que tengo para el selector de Objective-C que se debe pasar como un puntero a la función C:

- (void)myObjCSelector:(int*)myIntArray { // Do whatever I need with myIntArray }

2. Y aquí es donde me encuentro con una pared, Dentro de Objective-C Estoy tratando de pasar el selector como un puntero a la llamada de la función C: En lugar de " myObjCSelectorPointer " Necesito la sintaxis adecuada para pasar el selector como puntero de función en esta llamada de función C:

passObjCSelectorPointerToCContext(cContextReference, myObjCSelectorPointer);

Investigué este problema, pero principalmente pude encontrar varias formas diferentes de hacer cosas similares, pero no pude encontrar nada específico para llamar a las funciones de C y pasar un puntero selector de Objective-C.


¿Tienes que usar un puntero de función? En Objective-C, puede llevar el puntero a la función a una implementación de método arbitrario (conocida como IMP ), pero esto es extremadamente raro, y generalmente no es una buena idea. Llamar a objc_msgSend() directamente tampoco es la mejor idea, ya que hay varias variantes diferentes de objc_msgSend() , y el compilador elige automáticamente otras diferentes según el tipo de retorno del método. Los métodos que devuelven un objeto pasan por objc_msgSend() , pero los objetos que devuelven estructuras pueden pasar por objc_msgSend() o pueden pasar por objc_msgSend_stret() . Y si el método devuelve un double , entonces pasa por objc_msgSend_fpret() ...

Documentación: Referencia en tiempo de ejecución de Objective-C: Envío de mensajes

En su lugar, podría recomendar el uso de un par objetivo-acción, o el uso de un bloque. Entonces podrías hacer algo como:

myContextRef->target = anObjcObject; myContextRef->action = @selector(invokeMe:);

Y cuando hayas terminado, haz:

[myContextRef->target performSelector:myContextRef->action withObject:someReturnInformation];

O tal vez use un bloque:

myContextRef->completionHandler = [^(id returnInformation) { [anObjcObject invokeMe:returnInformation]; } copy];

Y luego, cuando hayas terminado, haz:

myContextRef->completionHandler(someReturnInformation);

(y no te olvides de -release el bloque cuando -release el contexto)


Básicamente, la respuesta es: los selectores Objective-C son diferentes de los punteros de función. Necesitas dos datos para realizar un selector. Eso es un objeto y el propio selector. Necesitarás un poco de pegamento para realizar tu tarea.

Compruebe this pregunta.


En objc un selector no es un puntero de función. Un selector es un entero único que se asigna a una cadena en una tabla de búsqueda de métodos almacenada por el tiempo de ejecución de objc. En el caso anterior, el nombre de su método sería myObjCSelector: y para obtener el selector único, debe escribir @selector(myObjCSelector:) . Sin embargo, esto no sería de ninguna utilidad porque no representa una implementación particular de una función.

Lo que estás buscando es IMP. Consulte this pregunta SO.

EDIT 2:

IMP myObjCSelectorPointer = (void (*)(id,SEL,int*))[self methodForSelector:@selector(myObjCSelector:)];

Entonces puedes llamar al método usando

myObjCSelectorPointer(self,@selector(myObjCSelector:),myIntArray);

Sin embargo, lo que esto significa es que debe asegurarse de que agrega el puntero a self en la función c llamada callObjCSelectorPointerToCContext. Así que debería verse así

passObjCSelectorPointerToCContext(cContextReference, self, myObjCSelectorPointer);

cuando se llama desde dentro del objeto que contiene el método.

Es importante tener en cuenta que el uso de IMP casi nunca es la técnica correcta. Debes tratar de mantenerte con Obj-C puro. Obj-C es bastante eficiente después de la primera llamada a un mensaje porque utiliza el almacenamiento en caché temporal.

EDITAR 1:

Es útil entender por qué objc funciona de esta manera. Los documentos de Apple lo explain en profundidad. Sin embargo, una breve explicación es la siguiente:

Cuando envía un mensaje a un objeto como [myobject somemethod] el compilador no sabrá inmediatamente a qué implementación particular de somemethod llamar, ya que puede haber múltiples clases con múltiples versiones anuladas de algún método. Todos estos métodos tienen el mismo selector, independientemente de sus argumentos y valores de retorno y, por lo tanto, la decisión acerca de qué implementación de algún método se difiere cuando el programa se está ejecutando. [myobject somemethod] se convierte por el compilador en una llamada a la función C:

objc_msgSend(myobject, @selector(somemethod))

Esta es una función especial que busca en cada myobject clase de myobject para ver si esa clase sabe cómo responder a un mensaje de algún somemethod . Si no es así, busca el padre de esa clase y así sucesivamente hasta la raíz. Si ninguna de las clases puede responder a somemethod , NSObject define un método privado llamado forward donde se envían todos los mensajes desconocidos.

Suponiendo que una clase pueda responder al mensaje de somemethod , también tendrá un puntero particular de tipo IMP que apunta a la implementación real del método. En ese punto se llamará el método.

Hay mucho más en este procedimiento de lo que he descrito, pero el esquema debería ser suficiente para ayudarlo a comprender cuál es el objetivo de un selector.

Un último punto es que los nombres de los métodos de razón se asignan a enteros únicos a través de la directiva @selector para que el tiempo de ejecución no tenga que perder tiempo haciendo comparaciones de cadenas.