- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
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]
- Etiquetas:
- Intel® Fortran Compiler
Enlace copiado
7 Respuestas
- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
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.
- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
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)
- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
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.
- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
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]
- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
And when the Intel Fortran will be full support for the standard 2003?
- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
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.
- Marcar como nuevo
- Favorito
- Suscribir
- Silenciar
- Suscribirse a un feed RSS
- Resaltar
- Imprimir
- Informe de contenido inapropiado
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.

Responder
Opciones de temas
- Suscribirse a un feed RSS
- Marcar tema como nuevo
- Marcar tema como leído
- Flotar este Tema para el usuario actual
- Favorito
- Suscribir
- Página de impresión sencilla