Como tornar óbvio que uma função está sendo acessada de fora?

9

Esta é uma pergunta específica em C. Estou tentando manter todo o possível dentro dos limites da unidade de tradução, expondo apenas algumas funções através do .harquivo. Ou seja, estou dando staticligação a objetos no nível do arquivo.

Agora, algumas funções precisam ser chamadas por outros módulos, mas não diretamente. Meu módulo / arquivo / unidade de tradução assina os outros módulos, passando um ponteiro para uma função. Então, em um evento específico, o ponteiro é chamado com alguns argumentos.

Então, eu estou querendo saber como tornar muito óbvio que essas funções são chamadas de algum local obscuro.

  • Eles deveriam ser staticou extern(e expô-los no .h)?
  • Devo incluir alguma dica no nome das funções?
  • Ou é suficiente colocar um comentário "chamado por X"?
Vorac
fonte
11
Essa é uma excelente pergunta. Minha solução (com a qual não estou muito feliz, é por isso que estou colocando apenas um comentário) é criar vários arquivos de cabeçalho, com nome sensato e funções de agrupamento no escopo que eu quero que eles tenham. Para a biblioteca AStar eu fiz eu tenho AStar.h, AStar_private.h, AStar_packagePrivate.h, etc ...
Shivan Dragão

Respostas:

2

Da perspectiva da unidade de compilação (arquivo), a única coisa com que você deve se preocupar é se a função está ou não disponível para o exterior. Torná-lo disponível significa que ele deveria ser chamado e você deve operar com o pressuposto de que essas chamadas ocorrerão. Sua preocupação com a função em si começa no ponto de entrada. Como o controle chega lá em primeiro lugar, importa apenas para o código que faz com que isso aconteça.

Como o vínculo em todas as implementações do CI conhecido é simbólico, qualquer coisa que chama uma função deve se referir ao seu símbolo:

foo();  /* Direct */

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

Se você declarar erroneamente foo()a ser static, seu programa não vai ligar. Se você declarar que não static, você tem uma função exposta que não é chamada. Perguntas sobre o uso ou não de uma função podem ser resolvidas descartando as tabelas de símbolos dos arquivos de objetos ou pesquisando-as nas fontes.

Blrfl
fonte
1

Então, estou pensando em como tornar muito óbvio que essas funções são chamadas de algum local obscuro.

Defina "obscuro".
Os métodos devem ser expostos por meio de "interfaces" bem definidas e, como Shivan Dragon já sugeriu, essas "interfaces" são seus arquivos .h. Se você não der a outro programa o arquivo de cabeçalho "correto", ele não poderá chamar o método.

Eles devem ser estáticos ou externos (e expô-los no .h)?

static pode ser bom desde que você não tenha nenhuma classe [-like constructos] que contenha dados da instância.
externsignifica que você realmente não o implementa; uma implementação é "adquirida" de outro local durante o processo de vinculação.

Devo incluir alguma dica no nome das funções?

Ou é suficiente colocar um comentário "chamado por X"?

Absolutamente não.

Comentários como esse, por mais bem-intencionados, ficam obsoletos no momento em que você termina de escrevê-los.

Phill W.
fonte
Dirigindo-se ao seu primeiro ponto, as funções são chamadas da seguinte maneira. Meu componente inclui um .harquivo externo . Ele chama uma função a partir daí e fornece um ponteiro para uma das próprias funções do módulo. Posteriormente, o código externo chama o que estiver nesse ponteiro. Assim, minha função está sendo chamada por alguém, que não inclui meu arquivo de cabeçalho, mas eu incluo o dele.
Vorac
11
No que diz respeito ao segundo ponto, no que diz respeito ao meu entendimento, o objeto definido no escopo do arquivo tem um vínculo externo por padrão; portanto, a externpalavra-chave é redundante` .
Vorac
0

Se as funções de retorno de chamada forem definidas dentro do seu módulo e o usuário nunca fornecer uma, ele deverá ser utilizado como espaço reservado durante a fase de inicialização. O espaço reservado é normalmente um enumque é traduzido internamente para a staticfunção correta .

lorcap
fonte
0

Eu ainda os faria static(eles não pretendem ser vinculados e chamados por qualquer pessoa) e marcaria seu objetivo como retornos de chamada fornecidos a funções externas em seu nome.

static porque eu tento esconder o que posso esconder, tanto quanto posso esconder.

Marque-os em seu nome, porque a) os comentários ficam desatualizados eb), torna-se óbvio no local em que o retorno de chamada é fornecido que esta função deve ser usada dessa maneira: isso basicamente o torna uma bandeira vermelha para estar usando o endereço de uma função que não segue a convenção de nomenclatura.

Sebastian Redl
fonte
0

Modificadores de escopo devem ser usados ​​principalmente como informações para o compilador, não como uma forma de documentação "suficientemente próxima". O uso de, staticem particular, permite que um compilador C torne a função inutilizável de fora do módulo, incluindo um retorno de chamada - não o que você deseja, mesmo que possa funcionar com o seu compilador atual.

É claro que você deve adicionar um comentário ao código, pois pode ser uma situação potencialmente confusa. Qualquer coisa incomum ou inesperada precisa de um comentário adequado. Mas, como afirmado em outras respostas, os comentários podem não ser lidos ou ficar desatualizados.

Portanto, a única opção que resta é nomear a função para indicar que é um retorno de chamada. A maioria dos exemplos que eu vi usar _callbackou _cbcomo um sufixo ou cb_como um prefixo. Use o formulário longo se retornos de chamada forem incomuns no seu código, o formulário curto se eles forem comuns.

Jonathan Giddy
fonte