I would like to call this C function from Fortran using the C interop
in F03:
> cat test.c
#include "stdio.h"
void test(int i,char* name[]) {
int k;
for (k=0;k<i;k++) {
printf("%d %s\n",i,name[k]);
}
}
The tricky bit for me is the 'char* name[]' declaration.
I've come to something that looks really ugly but 'works' with xlf90:
> cat cinterop.f
USE ISO_C_BINDING, ONLY : C_INT,C_CHAR,C_NULL_CHAR,C_PTR,C_LOC
IMPLICIT NONE
INTERFACE
SUBROUTINE TEST(I,name) BIND(C)
USE ISO_C_BINDING, ONLY : C_INT,C_PTR
IMPLICIT NONE
INTEGER(C_INT), VALUE :: I
TYPE(C_PTR), DIMENSION(*) :: name
END SUBROUTINE TEST
END INTERFACE
INTEGER(C_INT) :: I
CHARACTER(KIND=C_CHAR), TARGET :: name1(10)
CHARACTER(KIND=C_CHAR), TARGET :: name2(10)
CHARACTER(LEN=10,KIND=C_CHAR) :: str1
CHARACTER(LEN=10,KIND=C_CHAR) :: str2
TYPE(C_PTR), DIMENSION(2) :: cname
I=2
str1=C_CHAR_"1234"//C_NULL_CHAR
str2=C_CHAR_"abcd"//C_NULL_CHAR
FORALL(i=1:10) name1(i)=str1(i:i)
FORALL(i=1:10) name2(i)=str2(i:i)
cname(1)=C_LOC(name1)
cname(2)=C_LOC(name2)
CALL TEST(I,cname)
END
> xlc -c test.c ; xlf90 cinterop.f test.o ; ./a.out
** _main === End of Compilation 1 ===
1501-510 Compilation successful for file cinterop.f.
0 1234
1 abcd
I'm wondering if this is indeed standard conforming and/or if there is
an easier solution.
Thanks,
Joost
> I would like to call this C function from Fortran using the C interop
> in F03:
[elided]
> I'm wondering if this is indeed standard conforming and/or if there is
> an easier solution.
I think it is ok, based on a quick skim. As for the mess, the procedure
declaration looks simple enough. The only thing "messy" I see is copying
the thing from the string to the arrays of chars. Why did you bother
with that? Seems unnecessary....oh....maybe not....hmm. Apparently you
can't apply c_loc to a string. That seems to me like an oversight.
Strings are special-cased specifically so that you can pass them to C
functions without copying them to arrays of char. But I don't see a
similar special case for c_loc.
Of course, you could cut down a little by making a big single array
instead of multiple smaller ones, but that's a relatively minor detail
and I'm not convinced it would actually even be an improvement.
--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
> hmm. Apparently you
> can't apply c_loc to a string. That seems to me like an oversight.
> Strings are special-cased specifically so that you can pass them to C
> functions without copying them to arrays of char. But I don't see a
> similar special case for c_loc.
I just emailed the J3 list suggesting that the inability to do C_LOC on
a string is an oversight that ought to be fixed (at least in f2008, and
arguably that it might even be an obvious and simple enough oversight to
merit an f2003 corrgendum item, though I don't at all know whether that
will fly).
In the meantime, a stupid workaround occurs to me. Although you can't
pass a character string of length>1 to C_LOC, you can pass it to an
"ordinary" C function. You could write your own C function to do the
equivalent of C_LOC for such a string. Heck, you could then even give it
the generic name C_LOC, in which case it would override the intrinsic
C_LOC for character args. I think that would work. Ok, it is even
"uglier" than what you have, but the "ugliness" can be hidden away
instead of intruding into the middle of what you are trying to do.
I hope this makes it as a F2003 corrigendum...
Many thanks,
Joost