Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

334
Views
gfortran: pasa el argumento lógico a la función Fortran desde C

¿Qué tipo de argumento debo usar en C al llamar a una función Fortran que toma argumentos logical , específicamente con gfortran? ¿Dónde está documentado esto para gfortran?

Aquí hay un programa de ejemplo que no se compila sin advertencias:

Contenido de one.f :

 subroutine proc1(x) logical x end

Contenido de main.c :

 void proc1_(_Bool *x); int main() { _Bool x; proc1_(&x); return 0; }

Si compilo usando GCC de la siguiente manera, con LTO habilitado, recibo una advertencia sobre prototipos de funciones que no coinciden:

 gfortran -flto -c one.f gcc -flto -c main.c gcc -flto main.o one.o

La advertencia que recibo:

 main.c:2:6: warning: type of 'proc1_' does not match original declaration [-Wlto-type-mismatch] 2 | void proc1_(_Bool *x); | ^ one.f:2:22: note: 'proc1' was previously declared here 2 | subroutine proc1(x) | ^ one.f:2:22: note: code may be misoptimized unless '-fno-strict-aliasing' is used

Tenga en cuenta que habilitar LTO le permite al enlazador verificar que los tipos de argumentos coincidan entre prototipos. Desafortunadamente, usar LTO no es nuestra elección. CRAN requiere que el código enviado se compile sin estas advertencias con LTO habilitado.

Solo veo problemas cuando trato de usar argumentos logical . real , integer y character están todos bien.

Se le puede pedir a gfortran que produzca prototipos en C, y este es el resultado que me da:

 gfortran -flto -fc-prototypes-external -c one.f
 void proc1_ (int_fast32_t *x);

Usar int_fast32_t en el prototipo C tampoco funciona. Ningún tipo que probé lo hizo, ni int , ni _Bool . Por lo general, cuando hay una discrepancia de tipos entre los prototipos, el mensaje de error menciona cuál debería ser el tipo, pero no en este caso.

¿Cómo puedo encontrar cuál es el tipo correcto para usar?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Para una interoperabilidad C-Fortran realmente moderna, debe usar los tipos (tipos) proporcionados por el módulo iso_c_binding y hacer que su procedimiento Fortran se bind(c) . De esa manera puedes usar logical(c_bool) .

Al estilo antiguo, lo mejor es trabajar con enteros y pasar un int y solo corregir de integer a logical dentro de Fortran. La antigua C no tenía ningún bool , se agregó más tarde.

Con cambios mínimos:

 subroutine proc1(x) use iso_c_binding logical(c_bool) x end
 #include <stdbool.h> void proc1_(bool *x); int main() { bool x; proc1_(&x); return 0; }
 > gfortran -flto -c one.f > gcc -flto -c main.c > gcc -flto main.o one.o

no emite ninguna advertencia en mi Linux y GCC 7 y 10.

O después de más cambios:

 subroutine proc1(x) bind(C, name="proc1") use iso_c_binding logical(c_bool), value :: x end
 #include <stdbool.h> void proc1(bool x); int main() { bool x; proc1(x); return 0; }

El cambio a pasar por valor, por supuesto, solo cuando de hecho es solo un parámetro de entrada.

over 4 years ago · Santiago Trujillo Report

0

La solución portátil correcta y garantizada es, como se explica en la respuesta de Vladimir F, crear una rutina de envoltura Fortran que use ISO_C_BINDING. Este contenedor también puede aprovechar la oportunidad para hacer una interfaz C más idiomática, por ejemplo, usando el especificador de value para pasar escalares por valor.

Sin embargo, para la solución rápida y sucia que funciona en GFortran SIN LTO (y algo probable en otros compiladores, pero no hay garantías), consulte https://gcc.gnu.org/onlinedocs/gfortran/Internal-representation-of-LOGICAL- variables.html#Representación-interna-de-variables-LOGICAS . Es decir, puede pasar una variable entera de C del tamaño apropiado que contenga 1 para verdadero y 0 para falso. Tamaño apropiado aquí, lo que significa que, a menos que haya compilado su código Fortran con -fdefault-integer-8 o tales opciones de compilación, el tipo lógico predeterminado de GFortran será de 4 bytes, por lo que un C int simple debería ser bueno (o int32_t si realmente desea asegúrese, aunque no creo que GFortran admita ningún objetivo en el que C int no sea de 32 bits).

La razón por la que esto no funciona con LTO es que, si bien lo anterior funciona, en las entrañas de GCC, las variables LÓGICAS de Fortran son casi las mismas que los números enteros, pero no del todo. Entonces, en la práctica, son variables enteras especiales con un valor máximo de 1 y un valor mínimo de 0, aunque ocupan más espacio (según lo especificado por su tipo de parámetro). Por lo tanto, es probable que este tipo de discrepancia de tipo sea de lo que se queja. Desafortunadamente, no hay solución para esta, excepto la solución correcta anterior a través de ISO_C_BINDING.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!