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

calling .c from fortran

da1cj
Beginner
739 Views
I basically want to call the following struct in .c from fortran as follows
...
struct AZNames{
int Number;
char *Name;
char *Unit;
int Typ;
};

static struct AZName AZLNames[] = {
{1, "Interaction G(%d)" , "Sa", 1}
{2, "Object H(%d)" , "Da", 3}
{3, "Action G(%d)" , "Fa", 2}
}

... what I really want to achieve is a state in fortran in which if I give in a randomlly selected number i.e 1, 2 or 3 ..., I recieve the corresponding Name, unit and Typ as stated in the struct.


... I have tried out a couple of methods calling this struct from fortran but still pretty much not close to my aim.

:-l
0 Kudos
4 Replies
Jugoslav_Dujic
Valued Contributor II
739 Views
Possible Fortran equivalents are:
TYPE AZnames
   INTEGER:: Number
   CHARACTER(xxx), POINTER:: Name => NULL()
   CHARACTER(xxx), POINTER:: Unit => NULL()
   INTEGER:: Typ
END TYPE
or
TYPE AZnames
   INTEGER:: Number
   INTEGER(INT_PTR_KIND()):: Name
   INTEGER(INT_PTR_KIND()):: Unit
   INTEGER:: Typ
END TYPE
Underlying CVF implementation of CHARACTER(), POINTER happens to be the same as char*. You should put some sufficiently big value instead of xxx to be able to hold the longest value. It's not clear from your post who fills in the structure (C or Fortran) -- if it's Fortran, you must take care to ALLOCATE Name and Unit before use (but you must not if it's C). The second translation would require use of LOC() routine. (I'd recommend the first unless you need portability).

Also, pay attention that strings coming from C must be � (char(0)) terminated, and whatever comes after that is undefined.

HTH
Jugoslav
0 Kudos
Intel_C_Intel
Employee
739 Views
You might need a
SEQUENCE
statement after the
TYPE
statement. This ensures that the compiler doesn't optimise the order of the entries in the structure, and make it different from the C code.

All the best,
Eddie
0 Kudos
da1cj
Beginner
739 Views
I understand your replies.

However I transformed the tip as such that if I can basically extract the data from .c and then pass it to a fortran subroutine which can thus be called up from any other fortran programm.

I guess that was going to get me to my aim,which is to use the data in .c by calling it from Fortran, which I guess you probably missunderstood because of my inexplicit explanation.

Nevertheless, I tried the following below,... it compiled the fortran subroutine sure without error but in trying to build an exe it gave out 2 Erroes

unresolved external _MAIN
unresolved external _EXTRACT

I have tried to correct this error with little success.

main()
{
f1 (AZLNames);
return;
}

void extract (struct AZNames* a, int* ix, int* Number, char* Name, char* Unit, i
nt* Typ)
{
*Number = a[*ix-1].Number;
strcpy(Name, a[*ix-1].Name);
strcpy(Unit, a[*ix-1].Unit);
*Typ = a[*ix-1].Typ;
}

C ------ Fortan subroutine ------
subroutine f1(a)
character*80 a

character*80 name, unit
integer*4 number, typ, ix

ix = 2
call extract(a, ix, number, name, unit, typ)
print *, number, name, unit, typ
return
end

...can possibly someone help out to get me out of this error or basically something new to get me to the goal of being able to use the data in the struct form from .c calling it from fortran 90 such that if I give in the Number I should recieve thecorresponding Name, Unit and Type.

Pls: See earlier post from me to this topic
0 Kudos
Jugoslav_Dujic
Valued Contributor II
739 Views
Did you read the Mixed-Language Programming chapter in Programmer's Guide? The error comes from the fact that Visual C++ mangles names as-is, while in Intel Fortran the default is uppercase -- linker searches for _EXTRACT, but finds only _extract.

You should specify an INTERFACE block for extract in Fortran code to tell the compiler what extract really is (and CHARACTER data type is not the best choice for representation -- there are hidden length arguments around -- use something else):
subroutine f1(a)
integer:: a

character*80 name, unit
integer*4 number, typ, ix

interface
  subroutine extract(a, ix, number, name, unit, typ)
  !dec$attributes C, REFERENCE:: extract
  integer:: a, ix, number, typ
  !dec$attributes REFERENCE:: name
  !dec$attributes REFERENCE:: unit
  character(*):: name
  character(*):: unit
  end subroutine extract
end interface
ix = 2
call extract(a, ix, number, name, unit, typ)
!It's probably a good idea to strip trailing char(0):
name = name(1:index(name,char(0)))
unit = unit(1:index(unit,char(0)))
print *, number, name, unit, typ
return
end
Jugoslav
0 Kudos
Reply