¿Cómo hacer obvio que se accede a una función desde el exterior?

9

Esta es una pregunta específica de C. Estoy tratando de mantener todo lo posible dentro de los límites de la unidad de traducción, exponiendo solo unas pocas funciones a través del .harchivo. Es decir, estoy dando staticenlace a objetos a nivel de archivo.

Ahora, otros módulos deben llamar a un par de funciones, pero no directamente. Mi módulo / archivo / unidad de traducción se suscribe a los otros módulos, pasando un puntero a una función. Luego, en un evento específico, se llama al puntero con algunos argumentos.

Así que me pregunto cómo hacer que sea muy obvio que esas funciones se invocan desde una ubicación oscura.

  • ¿Deberían ser statico extern(y exponerlos en el .h)?
  • ¿Debo incluir alguna pista en el nombre de las funciones?
  • ¿O es suficiente para poner un comentario "llamado por X"?
Vorac
fuente
1
Esa es una excelente pregunta. Mi solución (con la que no estoy nada contento, es por eso que solo lo pongo en un comentario) es hacer múltiples archivos de encabezado, con nombres razonables y funciones de agrupación en el alcance que quiero que tengan. Para la biblioteca AStar que hice, tengo AStar.h, AStar_private.h, AStar_packagePrivate.h, etc ...
Shivan Dragon

Respuestas:

2

Desde la perspectiva de la unidad de compilación (archivo), lo único que debe preocuparle es si la función está disponible o no en el exterior. Ponerlo a disposición significa que estaba destinado a ser llamado, y debe operar bajo el supuesto de que esas llamadas se realizarán. Su preocupación por la función en sí comienza en su punto de entrada. La forma en que el control llega allí en primer lugar es importante solo para el código que lo hace posible.

Dado que el enlace en cada implementación de CI es simbólico, cualquier cosa que llame a una función debe referirse a su símbolo:

foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */

Si por error declaras foo()ser static, tu programa no se vinculará. Si declara que no static, tiene una función expuesta que no se llama. Las preguntas sobre si se utiliza o no una función se pueden resolver volcando las tablas de símbolos de sus archivos de objetos o buscándolas en las fuentes.

Blrfl
fuente
1

Así que estoy divagando cómo hacer que sea muy obvio que esas funciones se invocan desde una ubicación oscura.

Definir "oscuro".
Los métodos deben exponerse a través de "interfaces" bien definidas y, como Shivan Dragon ya ha sugerido, esas "interfaces" son sus archivos .h. Si no le da a otro programa el archivo de encabezado "correcto", entonces no puede llamar al método.

¿Deberían ser estáticos o externos (y exponerlos en el .h)?

static puede estar bien siempre que no tenga ninguna clase [construcciones similares] que contengan datos de instancia.
externsignifica que en realidad no lo implementas en absoluto; una implementación se "adquiere" de otra parte durante el proceso de vinculación.

¿Debo incluir alguna pista en el nombre de las funciones?

¿O es suficiente para poner un comentario "llamado por X"?

Absolutamente no.

Comentarios como este, por muy bien intencionados que sean, son obsoletos en el momento en que termina de escribirlos.

Phill W.
fuente
Al abordar su primer punto, las funciones se llaman de la siguiente manera. Mi componente incluye un .harchivo externo . Llama a una función desde allí y le da un puntero a una de las funciones del módulo. Más tarde, el código externo llama a lo que esté en ese puntero. Por lo tanto, mi función está siendo llamada por alguien que no incluye mi archivo de encabezado, sino que incluyo el suyo.
Vorac
1
Con respecto al segundo punto, en lo que a mi entender se refiere, el objeto, definido en el alcance del archivo, tiene un enlace externo por defecto; por lo tanto, la externpalabra clave es redundante` .
Vorac
0

Si las funciones de devolución de llamada se definen dentro de su módulo y el usuario nunca proporcionará una propia, creo que puede usar un marcador de posición durante la fase de inicialización. El marcador de posición es típicamente un enumque luego se traduce internamente a la staticfunción correcta .

lorcap
fuente
0

Todavía los haría static(no están destinados a ser vinculados y llamados por cualquiera), y marcaría su propósito como devoluciones de llamada suministradas a funciones externas en su nombre.

static porque trato de ocultar lo que puedo ocultar, tanto como puedo ocultarlo.

Márcalos en su nombre, porque a), los comentarios se desactualizan, yb), resulta obvio en el lugar donde se proporciona la devolución de llamada que esta función está destinada a usarse de esa manera: esto básicamente hace que sea una señal de alerta para tomar la dirección de una función que no sigue la convención de nomenclatura.

Sebastian Redl
fuente
0

Los modificadores de alcance deben usarse principalmente como información para el compilador, no como una forma de documentación "lo suficientemente cercana". El uso de, staticen particular, permite que un compilador de C haga que la función sea inutilizable desde fuera del módulo, incluso como una devolución de llamada, no lo que desea, a pesar de que puede funcionar con su compilador actual.

Por supuesto, debe agregar un comentario al código, ya que puede ver que es una situación potencialmente confusa. Cualquier cosa inusual o inesperada necesita un comentario adecuado. Pero, como se indicó en otras respuestas, los comentarios pueden no leerse o quedar desactualizados.

Entonces, la única opción que queda es nombrar la función para indicar que es una devolución de llamada. La mayoría de los ejemplos que he visto usan _callbacko _cbcomo sufijo, o cb_como prefijo. Use la forma larga si las devoluciones de llamada son inusuales en su código, la forma corta si son comunes.

Jonathan Giddy
fuente