Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

C procedure call from Fortran

Wagner__Urs
Novice
435 Views

Hello

My task is it the replace a dll written in C which is called from fortran.

In the documentation the fortran declation of the subroutine is:

SUBROUTINE GUREC(LDR, DATREC, IIl, IRL, ERRIND, IL, IA, RL, RA, SL, LSTR, STR)
INTEGER     LDR
CHARACTER*80 DATREC(LDR)
INTEGER IIL
INTEGER IRL
INTEGER ISL
INTEGER ERRIND
INTEGER IL
INTEGER IA(IIL)
INTEGER RL
INTEGER RA(ISL)
INTEGER SL,
INTEGER LSTR(ISL)
CHARACTER*(*) STR(*)

How must I define the c function?

Especially the definiton of the last parameter STR is not clear.

Is this definition correct?

_declspec(dllexport) void GUREC(int *ldr, char(*datrec)[80], int *iil, int *irl, int *isl, int *errind, int *il, int *ia,
		int *rl, float *ra, int *sl, int *lstr, char *str, int str_len);

 

Thanks for Your answer.

Urs

0 Kudos
3 Replies
Steve_Lionel
Honored Contributor III
435 Views

Short answer: no.

Longer answer: In Fortran 2008, CHARACTER(*) is not interoperable with C. In general, character arguments are problematic because Fortran compilers pass character lengths in different ways. Having an array of character values is even more of a problem.  Also, you don't know that Fortran INTEGER is compatible with C int.

It is not really clear to me what you are asking. Do you have an existing Fortran procedure you want to rewrite in C? Are you asking how to call a C routine from Fortran? 

0 Kudos
Wagner__Urs
Novice
435 Views

I want to rewrite a C routine which is called from Fortran and  I don't have the source.

To only documentation that I have, is the specified Fortran declaration.

I am not completely shure how to call C routine from Fortran. In 32 Bit isn't INTEGER compatible with C int?

0 Kudos
mecej4
Honored Contributor III
435 Views

There are many ways of doing what you described; the more robust and portable you want the solution to be, the more reading you need to do and the more elaborate the code. The following is an error-prone but compact solution if your Fortran and C are for 32-bit Windows, and you are using Intel Fortran + Intel or MS C. The code assumes lots of things about the representations of variable types and calling conventions, which you will need to understand and document if you take this route. The way that the array of strings is handled is particularly bad, but it may work for now.

The Fortran driver for the C subroutine:

Program CallGUREC
implicit none
INTEGER, Parameter :: LDRM = 5, ISLM = 3, IILM = 4
CHARACTER(len=80):: DATREC(LDRM)
INTEGER LDR, IIL, IRL, ISL, ERRIND, IL, RL, SL
INTEGER :: IA(IILM), RA(ISLM), LSTR(ISLM)
CHARACTER(len=17) :: STR(7)
!
LDR = 3
IIL = 31
IRL = 15
ERRIND = 0
STR(3) = 'This is string 3'C
Call Gurec(LDR, DATREC, IIl, IRL, ERRIND, IL, IA, RL, RA, SL, LSTR, STR)
END PROGRAM

The C procedure:

#include <stdio.h>

void GUREC(int *ldr, char *daterec, int *iil, int *irl, int *errind,
  int *il,  int *ia, int *rl, int *ra, int *sl, int *lstr, char *str){
char *p=str;
printf("ldr = %d, iil = %d, irl = %d, errind=%d, STR(3)=str[2]='%s'\n",
   *ldr, *iil, *irl, *errind, p+2*17);
}

Note the uppercase name of the C procedure, the explicit null-termination of the string in the caller, and the explicit address calculation for the substring/string-array element in the callee. Any of these matters can give you trouble, and you have to decide whether you want such a quick-and-dirty solution or you should invest in a portable solution based on the Fortran-C Interoperability facilities.

0 Kudos
Reply