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

Communicating between Fortran TYPE and C++ structure

morethanair
Beginner
1,397 Views

Hi, all.

I wrote some test code using C DLL in Fortran.

I tested the memory matching between Fortran TYPE and C structure.

MODULE mod

TYPE test_t

INTEGER a

INTEGER b

INTEGER,POINTER::c(:)

REAL d

INTEGER e

INTEGER f

INTEGER g

END TYPE

END MODULE mod

PROGRAM main

USE mod

IMPLICIT NONE

TYPE(test_t) input

input%a=1

input%b=2

ALLOCATE(input%c(2))

input%c(1)=3

input%c(2)=4

input%d=5.5

input%e=6

input%f=7

input%g=8

call TEST(input)

END PROGRAM main

I simply put some values in Fortran code, and check it in C code like below.

typedef struct _test_t

{

int a;

int b;

int* c;

float d;

int e;

int f;

int g;

} test_t;

extern "C" __declspec(dllexport) void TEST(test_t* member)

{

printf("%f",member->d);

}

Before the pointer, the value are all right (a=1,b=2,c[0]=3,c[1]=4), but after then the values are distorted.

d=5.605e-045#DEN

e=-4

f=5

g=1

I guess the size of pointer in Fortran and C is different.

Anybody knows how to solve this problem?

Thank you.

0 Kudos
6 Replies
ZlamalJakub
New Contributor III
1,397 Views

If you compile 32 bit app, pointer size is 4 bytes does not matter on language.

I think that problem is that you use fortran pointer and not integer pointer. (I do not use fortran pointers so i do not have experience with this.

1. Are the values of a and b correct. if yes there is probably problem with c.

2. Try to put c at the end of structure.

Jakub

0 Kudos
morethanair
Beginner
1,397 Views

Thank you for the reply.

I tried to put the pointer at the end of the structure, and it works of course.

The problem is that I should use the structure containing several pointers.

To the first pointer, it works properly, but it has wrong values after that.

Is there any other idea?

0 Kudos
ZlamalJakub
New Contributor III
1,397 Views

Try following code

MODULE mod
TYPE test_t
INTEGER a
INTEGER b
INTEGER,POINTER::c(:)
integer d
INTEGER e
INTEGER f
INTEGER g
END TYPE

END MODULE mod



PROGRAM main
USE mod
IMPLICIT NONE
TYPE(test_t) input
integer*4 array(10)
pointer (parray,array)


input%a=1
input%b=2
input%d=5
input%e=6
input%f=7
input%g=8

parray=loc(input)
write(*,*) "size of input ",sizeof(input)
write(*,*) "values",array

ALLOCATE(input%c(2))
input%c(1)=3
input%c(2)=4

parray=loc(input) ! associate pointer
write(*,*) "size of input ",sizeof(input)
write(*,*) "values",array

write(*,*) "a address",loc(input.a)
write(*,*) "b address",loc(input.b)
write(*,*) "c address",loc(input.c)
write(*,*) "d address",loc(input.d)
write(*,*) "e address",loc(input.e)


END PROGRAM main

from addresses of members of structure (at the end of code) can be seen, that your structure is not in continuous block of memory (as is assumed by C code). You cannot use fortran pointers in structure if it is passed to C code

I modified member d to be integer to have the same type as array

Jakub

0 Kudos
ZlamalJakub
New Contributor III
1,397 Views

Try this code (it should work however I do not tested it).

MODULE mod
use ifwinty
TYPE test_t
INTEGER a
INTEGER b
integer(HANDLE) c
integer d
INTEGER e
INTEGER f
INTEGER g
END TYPE

END MODULE mod



PROGRAM main
USE mod
IMPLICIT NONE
TYPE(test_t) input

integer*4,allocatable :: c(:)

input%a=1
input%b=2
input%d=5
input%e=6
input%f=7
input%g=8

ALLOCATE(c(2))
c(1)=3
c(2)=4
input%c=loc(c) ! update pointer to data

call ...

END PROGRAM main

problem is that You should manage allocatable arrays separately of input structure and only update pointer to data input%c

Jakub

0 Kudos
ZlamalJakub
New Contributor III
1,397 Views

From the difference of adresses input.b amnd input.d (which should be 8 bytes - 4bytes of size a and 4bytes of size c) can be seen that FORTRAN adds another 32 bytes for pointer handling.

May be if you use your c structure like

typedef struct _test_t{

int a;

int b;

int* c;

int cpointerdummy[8]; // extra 8*4 bytes for FORTRAN pointer

float d;

int e;

int f;

int g;

} test_t;

your code should work as it was on the beginning

Jakub


0 Kudos
IDZ_A_Intel
Employee
1,397 Views
INTEGER,POINTER::c(:) isn't going to match anything reasonable in C, as Fortran will insert an array descriptor with many fields. I suggest instead using the type C_PTR from ISO_C_BINDING and assign its value using the C_LOC function from the same module. This will match what you expect in C.
0 Kudos
Reply