Writing to a C function that uses structs.

Writing to a C function that uses structs.

I am trying to write to a C function that has two structs in it.

void func_name (structIn *In, structOut *Out)

the first struct takes input from the fortran program, the structOut passes data back to the fortran program.

i am really a little lost on what the fortan side of it should look like. I have this so far which i pieced together from some sample code.

INTERFACE
SUBROUTINE func_name (BLOCKIN, BLOCKOUT )
!DEC$ ATTRIBUTES C :: func_name
!DEC$ ATTRIBUTES REFERENCE :: BLOCKIN
!DEC$ ATTRIBUTES REFERENCE :: BLOCKOUT
INTEGER BLOCKIN
END SUBROUTINE
END INTERFACE
INTEGER G
INTEGER B
INTEGER T
INTEGER R
INTEGER C
INTEGER P
INTEGER V
INTEGER S

CHAR(10) STRING1
CHAR(10) STRING2

COMMON /BLOCKIN/G, B, T, R, C, P, V, S
COMMON /BLOCKOUT/ STRING1, STRING2
. . .
CALL func_name( CBLOCKIN, BLOCKOUT )

there are a lot of pieces where I am unsure about the code.

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

You almost got it -- you should pass G and STRING1 to func_name. G and STRING1 are the first members of corresponding COMMONs -- I don't think you can use COMMON name anywhere in Fortran anywhere where context requires a variable. Oh yes, you should declare STRING1 as CHARACTER(*) within the INTERFACE block as well.

Note that you can match C prototype with TYPEs instead of COMMONs*; I like that approach more, since it provides richer capabilities (for example, you can declare more variables of appropriate TYPE but you'd have to write a new COMMON for each variable set) and is more semantically equivalent with C routine.

Jugoslav
----
* This involves some tricky scoping issues -- see this comp.lang.fortran thread

Jugoslav
www.xeffort.com

Oh yes, you should declare STRING1 as CHARACTER(*) within the INTERFACE block as well.

Obviously, that should be BLOCKOUT, not STRING1.

Jugoslav
www.xeffort.com

jugoslavdujic,
you wrote this "Note that you can match C prototype with TYPEs instead of COMMONs*; " can you elaborate on this just a little, im not sure what you mean. Im not the most experienced Fortran programmer...

Also, everything seems to compile alright now, except that i get the message error LNK2001: unresolved external symbol func_name when i put in a call to the function.

call func_name ( g, string1)
Any ideas?

thanks for the help

Re link error: func_name should be declared extern "C" in C code (in both .h file and .cpp file, prepend the function prototype with extern "C").

Re derived types: the following is semantically equivalent to your sample:

MODULE MyMod
TYPE T_Blockin
  SEQUENCE
  REAL G
  REAL H
  ...
END TYPE T_Blockin
TYPE T_Blockout
  SEQUENCE
  CHARACTER(10) String1
  CHARACTER(10) String2
END TYPE T_Blockout
  
END MODULE MyMod
!================
...
Use MyMod
INTERFACE
   SUBROUTINE func_name(Blockin, Blockout)
   !DEC$ATTRIBUTES C:: func_name
   !DEC$ATTRIBUTES REFERENCE:: Blockin
   !DEC$ATTRIBUTES REFERENCE:: Blockout
   USE MyMod !That's the tricky scoping part
   TYPE(T_Blockin):: Blockin
   TYPE(T_BlockOut):: Blockout
   END SUBROUTINE
END INTERFACE
TYPE(T_Blockin):: Blockin   !If you need these global,
TYPE(T_BlockOut):: Blockout !put them in MyMod
BlockIn%G = ...
CALL func_name(Blockin, Blockout)
WRITE(*,"(A,1x,A)") Blockout%String1, Blockout%String2

The advantage is that you can have as many BlockXXX variables as you want.

Jugoslav

Jugoslav
www.xeffort.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today