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

Dynamic Arrays from C/C++ to F90 - Cray Pointers?

cwr
Beginner
622 Views
I am trying to interface an F90 application with a set of library
functions written in C. The F90 program passes an array of data
to the C library which then generates an array of results that
I need to pass back to F90. The size of the results array is not
known until runtime, and is thus dynamically allocated within the
C library routines with a call to malloc. How do I pass the results
array back to F90? Can it be done without using array descriptors?

My first attempt is based on Cray pointers, and was inspired by a
previous post to the archived Visual Fortran forum:

http://softwareforums.intel.com/ids/board/message?board.id=15&message.id=795

The following source code is a test case for what I'm intending to
do. The main F90 program:

program test
interface
subroutine c_func(addr, size)
!DEC$ ATTRIBUTES C, REFERENCE::c_func
INTEGER :: addr, size
end subroutine c_func
end interface

integer :: s
real :: a(*)
pointer(addr, a)
call c_func(addr, s)
write(*,*) (a(i), i=1,s)
end program test


The C source code:


#include

void c_func(float* lp, int *s) {
int i = 0;
*s = 10;
lp = malloc(*s * sizeof(float));
/* Fill array with some data */
for (i = 0; i < *s; i++)
lp = i;
}


Compilation and execution from the command line:

[cwr f2c-test]$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--disable-checking --host=i386-redhat-linux --with-system-zlib
--enable-__cxa_atexit
Thread model: posix
gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7)
[cwr f2c-test]$ gcc -c c_func.c
[cwr f2c-test]$ ifort -V
Intel Fortran Compiler for 32-bit applications, Version 9.0 Build 20050430Z Package ID: l_fc_p_9.0.021
Copyright (C) 1985-2005 Intel Corporation. All rights reserved.
FOR NON-COMMERCIAL USE ONLY

ifort: Command line error: no files specified; for help type "ifort -help"
[cwr f2c-test]$ ifort -o test test.f90 c_func.o
[cwr f2c-test]$ ./test
1.0994554E-38 -1.8826277E-38 5.0475600E+14 -9.2033625E+30 -9.4037850E-38
9.9645707E-29 2.8870106E-02 -2.4651906E-32 -2.8571877E+11 2.3373590E-38


Clearly, something is not right. I am at a loss. Can anyone offer some
hints or suggestions?

Thanks.

Chris Winter

Message Edited by cwr@arm.ac.uk on 08-18-2005 04:56 AM

0 Kudos
3 Replies
Steven_L_Intel1
Employee
622 Views
You don't show the C code, but a simple, one-dimensional C array can be passed directly to Fortran using the (*) bounds, or even with adjustable arrays (N), where N is a passed-in argument. Descriptors and pointers are not necessary. Just remember that C arrays start at origin 0, so you may want to use (0:*) or (0:N-1), assuming N is the number of elements.

Things get more complicated if you have "multidimensional" arrays in C, which tend to be arrays of pointers to arrays.
0 Kudos
cwr
Beginner
622 Views
Thanks for your reply, Steve. I thought about what you said, but
am still none the wiser. Here is the modified F90 and C code I'm
playing with at the moment:


program test

implicit none

interface
subroutine c_func(arr, size)
!DEC$ ATTRIBUTES C, REFERENCE::c_func
INTEGER :: size
REAL :: arr(*)
end subroutine c_func
end interface

integer :: s, i
real :: a(*)
call c_func(a, s)
write(*,*) (a(i), i=0,s-1)
end program test


The C code:


#include

void c_func(float* a, int *s) {
int i = 0;

/* Create an array of length 10 */
*s = 10;
a = malloc(*s * sizeof(float));

/* Fill in some values */
for (i = 0; i < *s; i++)
a = i;
}


When I compile the F90 code and link it in with the C function's
object code, I get the following error:


[cwr f2c-test]$ ifort -o test test.f90 c_func.o
fortcom: Error: test.f90, line 14: The assumed-size array must be a dummy argument.
real :: a(*)
----------^
compilation aborted for test.f90 (code 1)


Any ideas where I am going wrong here?

Once again, the basic idea is that I want to call a C function from F90
which'll create an array whose length is not known until runtime. I'd then
like to access the contents of this array in F90. "Multidimensionality"
is not a problem - once I've figured out this basic issue, I think I can
deal with multi-dimensions by flattening them to a 1-d array and building
them back up on the F90 side.

Cheers.

Chris Winter
0 Kudos
Steven_L_Intel1
Employee
622 Views
Sorry, I misunderstood what you wanted to do. The original Fortran code is correct, the C code is not. Here is what works:

#include 

void c_func(float** lp, int *s) {
int i = 0;
*s = 10;
*lp = malloc(*s * sizeof(float));
/* Fill array with some data */
for (i = 0; i < *s; i++)
(*lp) = i;
}


You are passing in the address of a pointer to an array of floats, not the address of the array. You have to get the dereferencing right.

Message Edited by sblionel on 08-18-2005 01:15 PM

0 Kudos
Reply