• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Evaluaciones
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

266
Vistas
Calcule el recuento de parámetros de función en tiempo de compilación

Tengo una biblioteca C (con encabezados C) que existe en dos versiones diferentes.

Uno de ellos tiene una función que se ve así:

 int test(char * a, char * b, char * c, bool d, int e);

Y la otra versión se ve así:

 int test(char * a, char * b, char * c, bool d)

(para lo cual e no se proporciona como parámetro de función, pero está codificado en la función misma).

La biblioteca o sus encabezados no definen / incluyen ninguna forma de verificar la versión de la biblioteca, por lo que no puedo usar #if o #ifdef para verificar un número de versión.

¿Hay alguna manera de que pueda escribir un programa en C que se pueda compilar con ambas versiones de esta biblioteca, dependiendo de cuál esté instalada cuando se compila el programa? De esa manera, los contribuyentes que quieran compilar mi programa pueden usar cualquier versión de la biblioteca y la herramienta podría compilarse con cualquiera.

Entonces, para aclarar, estoy buscando algo como esto (o similar):

 #if HAS_ARGUMENT_COUNT(test, 5) test("a", "b", "c", true, 20); #elif HAS_ARGUMENT_COUNT(test, 4) test("a", "b", "c", true); #else #error "wrong argument count" #endif

¿Hay alguna manera de hacer eso en C? No pude encontrar una manera.

La biblioteca sería libogc ( https://github.com/devkitPro/libogc ), que cambió su definición de if_config hace un tiempo, y me gustaría que mi programa funcione tanto con la versión anterior como con la nueva. No pude encontrar ningún identificador de versión en la biblioteca. Actualmente estoy usando una versión modificada de GCC 8.3.

over 3 years ago · Santiago Trujillo
7 Respuestas
Responde la pregunta

0

No veo ninguna forma de hacer eso con C estándar, si está compilando con gcc , una forma muy fea puede ser usar gcc aux-info en un comando y pasar la cantidad de parámetros con -D :

 #!/bin/sh gcc -aux-info output.info demo.c COUNT=`grep "extern int foo" output.info | tr -dc "," | wc -m` rm output.info gcc -o demo demo.c -DCOUNT="$COUNT + 1" ./demo

este fragmento

 #include <stdio.h> int foo(int a, int b, int c); #ifndef COUNT #define COUNT 0 #endif int main(void) { printf("foo has %d parameters\n", COUNT); return 0; }

salidas

 foo has 3 parameters
over 3 years ago · Santiago Trujillo Denunciar

0

Creo que no hay forma de hacer esto en la etapa de preprocesamiento (al menos no sin algunos scripts externos). Por otro lado, hay una forma de detectar la firma de una función en el momento de la compilación si está utilizando C11: _Generic . Pero recuerde: no puede usar esto en una macro como #if porque las expresiones primarias no se evalúan en la etapa de preprocesamiento, por lo que no puede elegir dinámicamente llamar a la función con la firma 1 o 2 en esa etapa.

 #define WEIRD_LIB_FUNC_TYPE(T) _Generic(&(T), \ int (*)(char *, char *, char *, bool, int): 1, \ int (*)(char *, char *, char *, bool): 2, \ default: 0) printf("test's signature: %d\n", WEIRD_LIB_FUNC_TYPE(test)); // will print 1 if 'test' expects the extra argument, or 2 otherwise

Lo siento si esto no responde a su pregunta. Si realmente no puede detectar la versión del archivo de encabezado de la biblioteca "stock", existen soluciones en las que puede #ifdef algo que solo está presente en una versión específica de esa biblioteca.

Este es solo un diseño de biblioteca horrible.

Actualización: después de leer los comentarios, debo aclarar a los futuros lectores que no es posible en la etapa de preprocesamiento, pero aún es posible en tiempo de compilación. Solo tendría que emitir condicionalmente la llamada de función según mi fragmento anterior.

 typedef int (*TYPE_A)(char *, char *, char *, bool, int); typedef int (*TYPE_B)(char *, char *, char *, bool); int newtest(char *a, char *b, char *c, bool d, int e) { void (*func)(void) = (void (*)(void))&test; if (_Generic(&test, TYPE_A: 1, TYPE_B: 2, default: 0) == 1) { return ((TYPE_A)func)(a, b, c, d, e); } return ((TYPE_B)func)(a, b, c, d); }

De hecho, esto funciona, aunque podría ser controvertido lanzar una función de esta manera. La ventaja es que, como dijo @pizzapants184, la condición se optimizará porque la llamada _Generic se evaluará en tiempo de compilación.

over 3 years ago · Santiago Trujillo Denunciar

0

Esto debe hacerse en la etapa de configure , usando un paso de prueba de Autoconf (o CMake, o lo que sea), básicamente, intentar compilar un pequeño programa que usa la firma de cinco parámetros y ver si se compila con éxito, para determinar qué versión de la biblioteca está en uso. Eso se puede usar para establecer una macro de preprocesador que puede usar en un bloque #if en su código.

over 3 years ago · Santiago Trujillo Denunciar

0

Si su compilador es un GCC reciente, por ejemplo, un GCC 10 en noviembre de 2020, puede escribir su propio complemento GCC para verificar la firma en sus archivos de encabezado (y emitir el preprocesador C apropiado y relacionado #define -s y/o #ifdef , à la GNU autoconf ). Su complemento podría (por ejemplo) llenar alguna base de datos sqlite y luego generaría algún archivo de encabezado #include -d.

Luego configuraría su automatización de compilación (por ejemplo, su Makefile ) para usar ese complemento GCC y los datos que ha calculado cuando sea necesario.

Para una sola función, este enfoque es excesivo.

Para algunos proyectos grandes, podría tener sentido, en particular si también decide codificar un validador de reglas de codificación específico del proyecto en su complemento GCC.

Escribir un complemento de GCC podría tomar semanas de su tiempo , y es posible que deba parchear el código fuente de su complemento cuando cambie a un futuro GCC 11.

Véanse también este borrador de informe y los proyectos europeos CHARIOT y DECODER (que financian el trabajo descrito en ese informe).

Por cierto, puede pedirles a los autores de esa biblioteca que agreguen algunos metadatos de versiones. La inspiración puede provenir de libonion, Glib o libgccjit .

Por cierto, como se comentó correctamente en este número , no debe usar una versión antigua sin mantenimiento de alguna biblioteca de código abierto. Use el que está trabajado.

Me gustaría que mi programa funcione tanto con la versión antigua como con la nueva.

¿Por qué?

hacer que su programa funcione con la versión antigua (sin mantenimiento) de libogc es una carga tanto para usted como para ellos. No entiendo por qué dependería de una biblioteca antigua sin mantenimiento, si puede evitarlo.


PD. Por supuesto, podría escribir un complemento para GCC 8. Recomiendo cambiar a GCC 10: mejoró.

over 3 years ago · Santiago Trujillo Denunciar

0

tu no

las herramientas con las que está trabajando están vinculadas estáticamente y no admiten el control de versiones. puede sortearlo usando todo tipo de trucos y consejos que se han mencionado, pero al final del día son parches feos de algo que está tratando de hacer que no tiene sentido en este contexto (kit de herramientas/entorno de código) .

usted diseña su código para la versión del kit de herramientas que ha instalado. es un requisito difícil. Tampoco entiendo por qué querrías diseñar tu código de gamecube/wii para permitir la construcción de diferentes versiones. el conjunto de herramientas cambia constantemente para corregir errores, suposiciones, etc.

Creo que deberías darte cuenta del tipo de trabajo fallido con el que estás lidiando aquí si necesitas o quieres hacer esto con un conjunto de herramientas en constante evolución.

También creo, pero esto se debe a que lo conozco a usted y su relación con DevKitPro, supongo que pregunta esto porque tiene una versión anterior instalada y sus compilaciones de CI no funcionarán porque usan una versión más nueva (de docker). es esto, o tiene varias versiones instaladas en su máquina para un proyecto diferente que crea (pero no actualizará la fuente por alguna extraña razón).

over 3 years ago · Santiago Trujillo Denunciar

0

Intentar admitir la compilación de código con varias versiones de una biblioteca estática no tiene ningún propósito útil. Actualice su código para usar la última versión y deje de hacer la vida más difícil de lo que debe ser.

over 3 years ago · Santiago Trujillo Denunciar

0

En el lenguaje C original de Dennis Ritchie, a una función se le podía pasar cualquier cantidad de argumentos, independientemente de la cantidad de parámetros que esperaba, siempre que la función no accediera a ningún parámetro más allá de los que se le pasaron. Incluso en plataformas cuya convención de llamada normal no podría acomodar esta flexibilidad, los compiladores de C generalmente usarían una convención de llamada diferente que podría admitirla a menos que las funciones estuvieran marcadas con calificadores como pascal para indicar que deberían usar la convención de llamada ordinaria.

Por lo tanto, algo como lo siguiente habría tenido un comportamiento completamente definido en el lenguaje C original de Ritchie:

 int addTwoOrThree(count, x, y, z) int count, x, y, z; { if (count == 3) return x+y+z; else return x+y; } int test() { return count(2, 10,20) + count(3, 1,2,3); }

Debido a que hay algunas plataformas en las que no sería práctico admitir tal flexibilidad de forma predeterminada, el estándar C no requiere que los compiladores procesen de manera significativa las llamadas a funciones que tienen más o menos argumentos de los esperados, excepto las funciones que se han declarado con un ... el parámetro "esperará" cualquier número de argumentos que sea al menos tan grande como el número de parámetros reales especificados. Por lo tanto, es raro que se escriba un código que aproveche la flexibilidad que estaba presente en el lenguaje de Ritchie. No obstante, muchas implementaciones seguirán aceptando código escrito para admitir ese patrón si la función que se llama está en una unidad de compilación separada de las personas que llaman, y se declara pero no se crea un prototipo dentro de las unidades de compilación que la llaman.

over 3 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda