- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
The C source code:
Compilation and execution from the command line:
Clearly, something is not right. I am at a loss. Can anyone offer some
hints or suggestions?
Thanks.
Chris Winter
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
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Things get more complicated if you have "multidimensional" arrays in C, which tend to be arrays of pointers to arrays.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
The C code:
When I compile the F90 code and link it in with the C function's
object code, I get the following error:
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, I misunderstood what you wanted to do. The original Fortran code is correct, the C code is not. Here is what works:
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.
#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

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