- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a Fortran subroutine which I want to call from C. One of the arguments is a derived type such as:
type :: pprop real*8 :: x1 real*8 :: x2 real*8 :: x3 real*8 :: x4 end type pprop
On the C side, what can I map this to? Will an array work as all the components are of the same type? Or do I have to map to a struct?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Technically, you can't map it to anything in C. If you wrote it this way:
use, intrinsic :: iso_c_binding ... type,bind(C) :: pprop real(C_DOUBLE) :: x1 real(C_DOUBLE) :: x2 real(C_DOUBLE) :: x3 real(C_DOUBLE) :: x4 end type pprop
Then you could use a struct of four doubles or an array of four doubles. The problem with the way you wrote it is that the Fortran standard allows the compiler to rearrange or pad the components. Adding bind(C) tells Fortran to lay out the type as C would. Now, the C compiler might choose to pad as well, meaning that using an array is not 100% guaranteed, but I expect this will work.
real*8 is an extension and it's better when writing interoperable code to use the defined kind constants.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Whether you use an array or a struct on the C side depends on what you wish to do in the C code. With the subroutine
subroutine Fsub(p) BIND(C,NAME='fSub') use, intrinsic :: ISO_C_BINDING type, BIND(C) :: pprop real(C_DOUBLE) :: x1,x2,x3,x4 end type pprop ! type(pprop) :: p ! p=pprop(1d0,1d-3,2d0,2d3) return end subroutine
you can use the C main program
#include <stdio.h> main(){ struct {double x1,x2,x3,x4; } p; double y[4]; fSub(&p); printf("%e %e %e %e\n",p.x1,p.x2,p.x3,p.x4); fSub(y); printf("%e %e %e %e\n",y[0],y[1],y[2],y[3]); }
which calls fSub() both ways.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I decided to try the struct avenue first. My end goal is actually Fortran callng C which then calls Fortran. I was asking above about the 1st half, of this however it turns out I haven't got the 2nd part working which I am looking now. I have a C file:
#include <stdlib.h> struct { double enth; double entr; double dens; double visc; double ther; double surf; double cp ; double cv ; double cs ; double sos ; double z ; } pprop; extern void co2_drv( int* opt, double* pres, double* temp, double* rg, double* qual, double* hf, double* sf, pprop* vap, // this is line 27 pprop* liq, int* err); _declspec(dllexport) int CO2_driver( int* opt, double* pres, double* temp, double* qual, double* hf, double* sf, pprop* vap, pprop* liq) { int err; double rg = -1.0; co2_drv( opt, pres, temp, &rg, qual, hf, sf, vap, liq, &err); return (err); }
which is supposed to call the Fortran function co2_drv:
subroutine co2_drv(opt, pres, temp, rg, qual, hf, sf, vap, liq, err) implicit none type, bind(C) :: pprop real*8 :: enth real*8 :: entr real*8 :: dens real*8 :: visc real*8 :: ther real*8 :: surf real*8 :: cp real*8 :: cv real*8 :: cs real*8 :: sos real*8 :: z end type pprop integer , intent(in ) :: opt real*8 , intent(inout) :: pres (kPa) real*8 , intent(inout) :: temp (K) real*8 , intent(in ) :: rg (kmol/m3) real*8 , intent(inout) :: qual real*8 , intent(inout) :: hf (kJ/kg) real*8 , intent(inout) :: sf (kJ/kg.K) type(pprop), intent(out ) :: vap type(pprop), intent(out ) :: liq integer , intent(out ) :: err ...
However I must have a syntax issue as I get:
CO2PVTWrapper.c(27): error C2143: syntax error : missing ')' before '*'
CO2PVTWrapper.c(27): error C2081: 'pprop' : name in formal parameter list illegal
CO2PVTWrapper.c(27): error C2143: syntax error : missing '{' before '*'
CO2PVTWrapper.c(28): error C2371: 'pprop' : redefinition; different basic types
CO2PVTWrapper.c(18) : see declaration of 'pprop'
CO2PVTWrapper.c(28): error C2143: syntax error : missing ';' before '*'
CO2PVTWrapper.c(29): error C2059: syntax error : 'type'
CO2PVTWrapper.c(29): error C2059: syntax error : ')'
CO2PVTWrapper.c(38): error C2143: syntax error : missing ')' before '*'
CO2PVTWrapper.c(38): error C2081: 'pprop' : name in formal parameter list illegal
CO2PVTWrapper.c(38): error C2143: syntax error : missing '{' before '*'
CO2PVTWrapper.c(39): error C2371: 'pprop' : redefinition; different basic types
CO2PVTWrapper.c(18) : see declaration of 'pprop'
CO2PVTWrapper.c(39): error C2143: syntax error : missing ';' before '*'
CO2PVTWrapper.c(39): error C2059: syntax error : ')'
CO2PVTWrapper.c(41): error C2054: expected '(' to follow 'liq'
I'm not a C programmer...
Once I get this bit working I'll have to address the 1st half again, ie. Fortran calling the above C function. I hear you about real*8, I will correct that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You may want to define a type pprop:
typedef struct {...} pprop;
otherwise you would have to use: struct pprop* vap,
Regards,
Arjen
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks that fixed my syntax errors, however I'm getting an unresolved external:
CO2PVTWrapper.obj : error LNK2019: unresolved external symbol _co2_drv referenced in function _CO2_driver
The Fortran function is in a library co2_thermo.lib which is included in the Additional Dependencies section of the C project. Am I missing something in my syntax?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry I see I need caps for co2_drv in the C function. Now that that part links, let me try the first bit again, Fortran calling C.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Adrian F. wrote:
Thanks that fixed my syntax errors, however I'm getting an unresolved external:
CO2PVTWrapper.obj : error LNK2019: unresolved external symbol _co2_drv referenced in function _CO2_driver
The Fortran function is in a library co2_thermo.lib which is included in the Additional Dependencies section of the C project. Am I missing something in my syntax?
See BIND(C, Name'..) aspect in mecej4's post above.
See Dr Fortran's blog on recent books on Fortran: https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world. If you don't have a copy already, get Metcalf et al.'s Modern Fortran Explained; read the section on C interoperability.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page