2011-02-28 7 views
5

Me sale esta pregunta de este blog chino http://chenyufei.info/blog/2011-02-28/wrap-c-function-closure-gcc-nested-function/ El autor desea utilizar el cierre en el lenguaje c, y encontró que GCC tiene la capacidad de función anidada (y cierre). Por ejemplo:Acerca del wrapper y llame a la función C

typedef int (*func_t)(int arg); 


int foo(int a) { 

    return a + 1; 

} 


func_t create_wrap_function(func_t f) { 

    int wrapped(int arg) { 

     // call original function 

     int val = f(arg); 

     fprintf(log_func_call, "arg: %d ret: %d", arg, val); 

     return val; 
    } 

    return wrapped; 
} 

Pero no es solución común. create_wrap_function tiene un formato de función fijo, porque func_t limita el formato.

Como sabemos, Lua tiene cierre, y podría llamar a la función C también. Lo que deseo implementar es: Las funciones que queremos llamar son foo1 y foo2, tienen diferentes tipos de argumentos y valor de retorno.

int foo1(int a) { 
    ... 
    return intValue; 
} 

double foo2(char* str, double a) { 
    ... 
    return dblValue; 
} 

En cliente C, llamar a la función como:

lua_returnValue returnValue1 = Do_Lua_Wrap(__FILE__, __LINE__, foo1, 1); 
lua_returnValue returnValue2 = Do_Lua_Wrap(__FILE__, __LINE__, foo2, "string data", 1.2345); 

En el Do_Lua_Wrap, pasará la foo1 y 1 a la función Lua, a continuación, llamar foo1 función como proceso normal. Luego pase el foo2 y un char * y un doble valor a la función Lua, luego llame a la función foo2 como un proceso normal. En la función Lua, podría registrar la información sobre ARCHIVO y LÍNEA y escribir algún registro extra sobre los argumentos de la función.

Pero no tengo idea acerca de cómo escribir la función Do_Lua_Wrap en C y Lua, ¿Es posible?

Si es posible, ¿podría darme algunos consejos?

Respuesta

2

Usted está obviamente interesado en un variadic function, pero el problema es determinar el tipo de argumentos para presionar en la pila de Lua. Voy a recomendar un par de enfoques:

  1. La primera sería la de incluir una cadena formato al estilo de los printf familiares o envasado binaria formatos de uso frecuente en el nivel más alto idiomas. Por ejemplo, eche un vistazo a en el patrón de formato utilizado en el módulo lpack Lua. La clave es escanear a través del formato cadena a determinar cuántos y qué tipo de argumentos se proporcionan .

  2. Alternativamente, podría implementar un tipo variant. Cada argumento necesitaría estar envuelto en una estructura como . Además, el número total de argumentos debería proporcionarse como primer parámetro.

  3. Finalmente, podría pasar argumentos en dos matrices en lugar de utilizar una función variad . La primera matriz sería que contiene los tipos enumerados correspondientes al objetivo de void * punteros en la segunda matriz. Este método requiere la mayoría de las propiedades de la casa para el código del cliente, pero es bastante limpio.También se requerirá un argumento que especifique la longitud de las matrices o un valor de centinela al final de una o ambas matrices.

Afortunadamente, uno de esos métodos debería funcionar para usted. Personalmente, elegiría la primera opción y usaré el código lpack como guía. También viene lo más cerca posible de la firma de función especificada en su pregunta.

+0

¡Su respuesta es genial! – sagasw

Cuestiones relacionadas