Estoy tratando de burlarme de una función en C, la burla funciona bien cuando la función y la función de la persona que llama están definidas en archivos diferentes. Pero cuando ambas funciones (la función en sí y su llamador) se definen en el mismo archivo, la función simulada no se invoca.
Caso 1 :
//test.c #include <stdio.h> /*mocked function*/ int __wrap_func() { printf("Mock function !!!\n"); } /*caller function*/ int myTest() { return func(); } int main() { myTest(); return 0; } //file.c #include<stdio.h> /*function need to be mocked*/ int func() { printf("Original function !!!\n"); }
Caso 2:
//test.c #include <stdio.h> extern int myTest(); /*mocked function*/ int __wrap_func() { printf("Mock function !!!\n"); } int main() { myTest(); } //file.c #include<stdio.h> /*function need to be mocked*/ int func() { printf("Original function !!!\n"); } /*caller function*/ int myTest() { return func(); }
Comando de compilación de código: gcc -Wl,--wrap=func test.c file.c
In Case 1 . Mock function !!! In Case 2 . Original function !!!
En el caso 2, no se invoca la función de simulación. Estoy buscando una solución en la que pueda simular la función, incluso la función que llama y la llamada están en el mismo archivo.
El uso de un nombre de función que comienza con dos guiones bajos es un comportamiento indefinido en C.
(En su caso, sospecho que el nombre de la función __wrap_func
está en conflicto con el nombre decorado de func
, pero eso es especulativo y depende completamente del compilador).
Debería considerar una solución utilizando punteros de función en su lugar.
El uso de la opción de enlace --wrap=symbol
dará como resultado que los símbolos no definidos se resuelvan como __wrap_symbol
. En su primer caso, func
es un símbolo indefinido, por lo que el enlazador buscará __wrap_func
y se llamará a esa función. En su segundo caso, el enlazador encuentra myTest
porque se declara extern
. Cuando myTest
llama a func
, está en la misma unidad de traducción, por lo que no es indefenso que reside en el mismo archivo que int func()
. Entonces, la func
original es calles en lugar de la versión envuelta. Su diseño no es adecuado para usar funciones simuladas cuando la persona que llama y la persona que llama están en el mismo archivo y en archivos diferentes. Le sugiero que use MACRO
o la técnica del function pointer
como se explica aquí .
No se puede.
De la documentación del enlazador ,
--wrap símbolo Utilice una función de envoltura para el símbolo. Cualquier referencia indefinida al símbolo se resolverá como __wrap_symbol. Cualquier referencia indefinida a __real_symbol se resolverá como símbolo. Esto se puede utilizar para proporcionar un contenedor para una función del sistema. La función contenedora debe llamarse __wrap_symbol. Si desea llamar a la función del sistema, debe llamar a __real_symbol. Aquí hay un ejemplo trivial:
void * __wrap_malloc (int c) { printf ("malloc called with %ld\n", c); return __real_malloc (c); }
Si vincula otro código con este archivo usando --wrap malloc, entonces todas las llamadas a malloc llamarán a la función __wrap_malloc en su lugar. La llamada a __real_malloc en __wrap_malloc llamará a la función real malloc. Es posible que también desee proporcionar una función __real_malloc, de modo que los enlaces sin la opción --wrap tengan éxito.
Aquí está la parte importante...
Si hace esto, no debe poner la definición de __real_malloc en el mismo archivo que __wrap_malloc; si lo hace, el ensamblador puede resolver la llamada antes de que el enlazador tenga la oportunidad de envolverla en malloc.