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 .h
archivo. Es decir, estoy dando static
enlace 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
static
oextern
(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"?
c
naming
encapsulation
scope
Vorac
fuente
fuente
Respuestas:
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:
Si por error declaras
foo()
serstatic
, tu programa no se vinculará. Si declara que nostatic
, 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.fuente
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.
static
puede estar bien siempre que no tenga ninguna clase [construcciones similares] que contengan datos de instancia.extern
significa que en realidad no lo implementas en absoluto; una implementación se "adquiere" de otra parte durante el proceso de vinculación.Absolutamente no.
Comentarios como este, por muy bien intencionados que sean, son obsoletos en el momento en que termina de escribirlos.
fuente
.h
archivo 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.extern
palabra clave es redundante` .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
enum
que luego se traduce internamente a lastatic
función correcta .fuente
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.
fuente
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,
static
en 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
_callback
o_cb
como sufijo, ocb_
como prefijo. Use la forma larga si las devoluciones de llamada son inusuales en su código, la forma corta si son comunes.fuente