- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi! It took me a call from Fortran, some function of the static libraries in C. I used ISO_C_Binding, began to investigate, but three calls upeshen only one. What am I doing wrong?
[cpp]//C static lib. codeAnd Fortran code:
#include
//Calling of this function succes
void show(int x){
printf("Value = %dn",x);
}
//And other functions return wrong results
double copyVal(double A){
printf("C: A = %fn",A);
return A;
}
double getSum(int sz,double Arr[]){
int k = 0;
double Sum = 0;
printf("C: sz = %dn",sz);
printf("C: n");
for(k = 0; k[/cpp]
[plain]module mod_CData
use, intrinsic :: iso_c_binding;
implicit none;
interface
!void show(int x)
subroutine Show(x) bind(C,name = "show")
use, intrinsic :: iso_c_binding;
implicit none;
integer(c_int), value, intent(in) :: x;
end subroutine Show;
!double getSum(int sz,double *Arr)
real(c_double) function GetSum(sz, A) bind(C,name="getSum")
use, intrinsic :: iso_c_binding;
implicit none;
integer(c_int), value, intent(in) :: sz;
real(c_double), dimension(:) :: A;
end function GetSum;
!double copyVal(double A)
real(c_double) function CopyVal(x) bind(C,name = "copyVal")
use, intrinsic :: iso_c_binding;
implicit none;
integer(c_double), value :: x;
end function CopyVal;
end interface;
end module mod_CData
program Test_binding
use mod_CData;
integer(4), parameter :: M = 10;
integer(4) :: test_val;
real(8) :: res;
real(8),target,dimension(1:M) :: Arr;
real(8),pointer,dimension(:) :: pArr;
test_val = 10;
call Show(test_val);
print *,"c_int = ",c_int;
print *,"c_double",c_double;
Arr = (/10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0/);
print *,'Arr:'
print *,Arr;
pArr => Arr;
res = GetSum(size(Arr), pArr);
print *,'Res = ',res;
print *,'CopyVal = ', CopyVal(dble(100.0_8));
read(*,*);
end program Test_binding
Sorry for bad english.
Best regards, Dmitry
P.S. Visual Studio 2005 + Intel Fortran 10.1
Example project link: http://stream.ifolder.ru/11315393[/plain]
Link Copied
7 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In your Fortran interface for CopyVal, you declared the argument as integer(C_DOUBLE). You want real(C_DOUBLE) instead. The compiler should have given you an error similar to this:
t.f90(67): warning #6075: The data type of the actual argument does not match the definition. [DBLE]
print *,'CopyVal = ', CopyVal(dble(100.0_8));
------------------------------^
When you fix the declaration, you can also remove the "dble" from the call - just pass 100.0_8 (or 100.0_C_DOUBLE), though the dble is harmless here.
t.f90(67): warning #6075: The data type of the actual argument does not match the definition. [DBLE]
print *,'CopyVal = ', CopyVal(dble(100.0_8));
------------------------------^
When you fix the declaration, you can also remove the "dble" from the call - just pass 100.0_8 (or 100.0_C_DOUBLE), though the dble is harmless here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - popovdmitrya
Hi! It took me a call from Fortran, some function of the static libraries in C. I used ISO_C_Binding, began to investigate, but three calls upeshen only one. What am I doing wrong?
[plain]
!double getSum(int sz,double *Arr)
real(c_double) function GetSum(sz, A) bind(C,name="getSum")
use, intrinsic :: iso_c_binding;
implicit none;
integer(c_int), value, intent(in) :: sz;
real(c_double), dimension(:) :: A;
end function GetSum;
[/plain]
In addition, you can not use assumed-shape (:) arrays when interfacing with C. You need an assumed-size array (*) instead.
Steve, I think that the compiler should issue a warning in such cases, both for routines and INTERFACE blocks.
(Edit: In this particular case, it will happen to just work, because the array address is the first field in the array descriptor, but in principle it should be prohibited, as it may cause various nasty run-time errors)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't agree that it should be prohibited. The C routine could read the descriptor (we document it.) A proposed TR for F2008 adds support for C code to deal with Fortran descriptors in an implementation-independent fashion. But I agree that only explicit-shape or assumed-size arrays are "interoperable" by the terms of F2003, and the compiler could warn about non-interoperable arguments if standards checking was enabled. I'm somewhat uncomfortable with warning about this by default, though I can see the benefits in some cases.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you. Unfortunate typographical error, I found myself. Of course real (C_DOUBLE). So I tried to pass assumed-size array (*) instead of assumed-shape (:), but it still causes problems. Everything is working correctly after I began to pass a pointer to an array using C_PTR (fortran_array). But in this case is controlled by the situation that transferred real (C_DOUBLE), rather than, say, integer (C_LONGINT) or logical (1)?
Here's how I did:
Here's how I did:
[cpp]#includeFortran Interface:typedef struct CStruct{ int a; int b; char ch; double c[10]; } TCStruct; TCStruct globalS; void show(int x){ printf("C: Value = %dn",x); }//show int returnValue(int x){ printf("C: Value = %dn",x); return x; } void showArray(const int sz, double Arr[]){ int i = 0; printf("sz = %dn",sz); for(i = 0; i ); } }//showArray void getStruct(TCStruct *S){ int l; S->a = globalS.a*2; S->b = globalS.b*3; S->ch = globalS.ch +'0'; for(l = 0;l<10;l++){ S->c = globalS.c ; } printf("C: Struct is Get with differencen"); }//getStruct void setStruct(TCStruct S){ int l; printf("C: Struct is setn"); globalS.a = S.a; globalS.b = S.b; globalS.ch = S.ch; for(l = 0;l<10;l++){ globalS.c = S.c ; } }//getStruct[/cpp]
[plain]module mod_CInterfaces use, intrinsic :: iso_c_binding; implicit none; type CStructure sequence integer(c_int) :: a; integer(c_int) :: b; character :: ch; real(c_double),dimension(10) :: c; end type; interface subroutine Show(x) bind(C,name = "show") use, intrinsic :: iso_c_binding; integer(c_int), value, intent(in) :: x; end subroutine Show;And Fortran program
subroutine ShowArray(sz, Arr) bind(C,name = "showArray") use, intrinsic :: iso_c_binding; integer(c_int), value, intent(in) :: sz; type(c_ptr), value, intent(in) :: Arr; end subroutine ShowArray;
integer(c_int) function ReturnValue(x) bind(C,name = "returnValue") use, intrinsic :: iso_c_binding; integer(c_int), value, intent(in) :: x; end function ReturnValue; subroutine GetStruct(S) bind(C,name='getStruct') use, intrinsic :: iso_c_binding; type(c_ptr), value :: S; end subroutine GetStruct; subroutine SetStruct(S) bind(C,name='setStruct') use, intrinsic :: iso_c_binding; implicit none; type CStructure sequence integer(c_int) :: a; integer(c_int) :: b; character :: ch; real(c_double),dimension(10) :: c; end type; type(CStructure), value, intent(in) :: S; end subroutine SetStruct; end interface; end module mod_CInterfaces[/plain]
[plain]program Test_binding use mod_CInterfaces; implicit none; integer(4), parameter :: sz = 22; integer(4) :: test_val; real(8), dimension(:), allocatable :: Arr; type(CStructure) :: S; test_val = 10; call Show(test_val); print *,'Fortran: test_val = ',test_val; test_val = ReturnValue(test_val+sz); print *,'Fortran: test_val = ',test_val; allocate(Arr(1:sz)); Arr = 100.0; call ShowArray(sz, c_loc(Arr)); deallocate(Arr); S%a = 10; S%b = 20; S%ch = 'a'; S%c = (/1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 0.0/); call SetStruct(S); call GetStruct(c_loc(S)); write(*,*) 'Fortran: ',S; print *,'press ENTER'; read(*,*); end program Test_binding[/plain]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
And when the Intel Fortran will be full support for the standard 2003?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - popovdmitrya
# subroutine SetStruct(S) bind(C,name='setStruct')
# use, intrinsic :: iso_c_binding;
# implicit none;
#
# type CStructure
# sequence
#
# integer(c_int) :: a;
# integer(c_int) :: b;
# character :: ch;
# real(c_double),dimension(10) :: c;
# end type;
#
# type(CStructure), value, intent(in) :: S;
# end subroutine SetStruct;
# use, intrinsic :: iso_c_binding;
# implicit none;
#
# type CStructure
# sequence
#
# integer(c_int) :: a;
# integer(c_int) :: b;
# character :: ch;
# real(c_double),dimension(10) :: c;
# end type;
#
# type(CStructure), value, intent(in) :: S;
# end subroutine SetStruct;
1) You used SEQUENCE in the Fortran definition of the type. This has the side effect that it turns member packing to 1-byte (because SEQUENCE means it can be sequence-associated), so CStructure%C in Fortran follows immediately CStructure%ch, while in C there is 3-byte padding after ch. Get rid of the SEQUENCE. I think that you can use BIND(C) attribute for the structure, in which case you should have got a compiler warning (though I didn't check it myself)
2) You probably used SEQUENCE to workaround double-definition/interface block scope problem. That's a wrong cure in this case. Instead, use IMPORT keyword within the above-quoted INTERFACE block, to import the declaration of CStruct into the scope.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Jugoslav Dujic
Quoting - popovdmitrya
# subroutine SetStruct(S) bind(C,name='setStruct')
# use, intrinsic :: iso_c_binding;
# implicit none;
#
# type CStructure
# sequence
#
# integer(c_int) :: a;
# integer(c_int) :: b;
# character :: ch;
# real(c_double),dimension(10) :: c;
# end type;
#
# type(CStructure), value, intent(in) :: S;
# end subroutine SetStruct;
# use, intrinsic :: iso_c_binding;
# implicit none;
#
# type CStructure
# sequence
#
# integer(c_int) :: a;
# integer(c_int) :: b;
# character :: ch;
# real(c_double),dimension(10) :: c;
# end type;
#
# type(CStructure), value, intent(in) :: S;
# end subroutine SetStruct;
1) You used SEQUENCE in the Fortran definition of the type. This has the side effect that it turns member packing to 1-byte (because SEQUENCE means it can be sequence-associated), so CStructure%C in Fortran follows immediately CStructure%ch, while in C there is 3-byte padding after ch. Get rid of the SEQUENCE. I think that you can use BIND(C) attribute for the structure, in which case you should have got a compiler warning (though I didn't check it myself)
2) You probably used SEQUENCE to workaround double-definition/interface block scope problem. That's a wrong cure in this case. Instead, use IMPORT keyword within the above-quoted INTERFACE block, to import the declaration of CStruct into the scope.

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