2016-09-30 3 views
-1

Wie kann ich ein 2d-Array in Fortran zugreifen, die als Zeiger von C-Funktion übergeben wird. Unten ist mein CodeZugriff 2d Arrays von C als Zeiger in Fortran übergeben

program linkFwithC 
    use iso_c_binding 
    implicit none 
    interface 
     subroutine my_routine(p,r) bind(c,name='print2') 
     import :: c_ptr 
     import :: c_int 
     type(c_ptr), value :: p 
     integer(c_int), value :: r 
     end subroutine 
    end interface 
    REAL, POINTER :: PTR2 
    integer i,j 
    integer,parameter ::n=3 
    real (c_double), allocatable, target :: xyz(:,:) 
    real (c_double), target :: abc(3,3) 
    type(c_ptr) :: cptr 
    allocate(xyz(n,n)) 
    cptr = c_loc(xyz(1,1)) 

    !Inputing array valyes 

    xyz(1,1)= 1 
    xyz(1,2)= 2 
    xyz(1,3)= 3 
    xyz(2,1)= 4 
    xyz(2,2)= 5 
    xyz(2,3)= 6 
    xyz(3,1)= 7 
    xyz(3,2)= 8 
    xyz(3,3)= 9 


    call my_routine(cptr,n) 

    do j=1,n 
    do i=1,n 

    print*,"xyz(i,j)",i,j,xyz(j,i) 

    enddo 
    enddo 
    deallocate(xyz) 
! pause 
    end program linkFwithC 

Unter meinen C-Code ist

#include <stdio.h> 
    void print2(double *p, int n) 
    { 
    printf("Array from C is \n"); 
    double *dptr; 
    int i,j; 
    dptr = (double *)p; 
    for (i = 0; i < n; i++) 
    { 
    for (j = 0; j<n; j++) 
     { 
     printf("%.6g \t",dptr[i*n+j]); 

     *(p+i*n+j)=1; 
     printf("\n"); 
    } 
    } 
} 

unterhalb der Ausgang

Array from C is 
1  4  7 
1  5  8 
1  6  9 
xyz(i,j)   1   1 1.00000000000000 
xyz(i,j)   2   1 1.00000000000000 
xyz(i,j)   3   1 1.00000000000000 
xyz(i,j)   1   2 4.00000000000000 
xyz(i,j)   2   2 5.00000000000000 
xyz(i,j)   3   2 6.00000000000000 
xyz(i,j)   1   3 7.00000000000000 
xyz(i,j)   2   3 8.00000000000000 
xyz(i,j)   3   3 9.00000000000000 
*** glibc detected *** ./main.exe: free(): invalid next size (normal): 0x000000000093c290 *** 
======= Backtrace: ========= 
/lib64/libc.so.6[0x320ea75f4e] 
/lib64/libc.so.6[0x320ea78cf0] 
./main.exe[0x408786] 
./main.exe[0x4240bc] 
./main.exe[0x429f54] 
./main.exe[0x402e63] 
/lib64/libc.so.6(__libc_start_main+0xfd)[0x320ea1ed5d] 
./main.exe[0x402d69] 
======= Memory map: ======== 

ich nicht in der Lage bin die geänderten Werte in Fortran zu drucken. Kann irgendjemand vorschlagen, was möglicher Grund für die Lohnproduktion sein könnte?

+0

Sie schon viele Fragen wie diese gestellt: http://stackoverflow.com/questions/27584674/passing-2d-array-from-fortran -to-c, http://stackoverflow.com/questions/27582715/passing-a-two-dimensional-array-from-fortran-to-c –

+0

Sind Sie sicher, dass 2-dimensionale zuweisbare Arrays in Fortran haben zusammenhängende Speicher wie statische zweidimensionale Arrays? Denn das Ergebnis scheint das Gegenteil zu beweisen. Und vergessen Sie nicht, dass C & FORTRAN bei mehrdimensionalen Arrays transponiert sind. –

+0

@ Jean-FrançoisFabre Ja haben sie, tatsächlich sind sie immer zusammenhängendes Gedächtnis. Sie können nach einem Beispielprogramm googlen, das einen Zeiger von [tag: c] an * lapack * [tag: fortran] übergibt. –

Antwort

0

Zunächst ist Ihr Code nicht FORTRAN, sondern Fortran; Einrichtungen für die C-Sprachen-Interoperabilität kamen viel später. Zweitens wird der folgende Code

#include <stdio.h> 
void print2(double *p, int n) 
{ 
    double *dptr; 
    int i,j; 

    /* Why are you making a copy here? 
    * Did you intent to pass by value or reference? 
    */ 
    dptr = p; 
    printf("Array from C is \n"); 
    for(i = 0; i < n; i++){ 
    for(j = 0; j < n; j++){ 
     printf("%.6g \t", dptr[i*n+j]); 
     *(p+i*n+j)=1; 
     printf("\n"); 
    } 
    } 
} 

module mymod 

    use ISO_C_binding, only: & 
     c_ptr, & 
     c_int 

    ! Explicit typing only 
    implicit none 

    interface 
    subroutine my_routine(p, r) bind(c, name='print2') 
     import :: c_ptr, c_int 
     type(c_ptr), value :: p 
     integer(c_int), value :: r 
    end subroutine my_routine 
    end interface 

end module mymod 

program main 

    use ISO_Fortran_env, only: & 
    compiler_version, & 
    compiler_options 

    use ISO_C_binding, only: & 
    c_double, & 
    c_ptr, & 
    c_loc 

    use mymod, only: & 
    my_routine 

    ! Explicit typing only 
    implicit none 

    integer i, j 
    integer, parameter :: N = 3 
    real(c_double), allocatable, target :: xyz(:,:) 
    type(c_ptr) :: cptr 

    ! Allocate memory 
    allocate(xyz(N, N)) 

    ! Get C-language address 
    cptr = c_loc(xyz(1,1)) 

    ! Inputting array values 
    xyz(1,1)= 1 
    xyz(1,2)= 2 
    xyz(1,3)= 3 
    xyz(2,1)= 4 
    xyz(2,2)= 5 
    xyz(2,3)= 6 
    xyz(3,1)= 7 
    xyz(3,2)= 8 
    xyz(3,3)= 9 

    call my_routine(cptr, N) 

    do j=1, N 
     do i=1, N 
     print *, "xyz(i,j)", i, j, xyz(j, i) 
     end do 
    end do 

    ! Release memory 
    deallocate(xyz) 

    print '(/4a/)', & 
    ' This file was compiled using ', compiler_version(), & 
    ' using the options ', compiler_options() 

end program main 

ergibt

gfortran -Wall -o main.exe print2.c mymod.f90 main.f90 
./main.exe 

Array from C is 
1 
4 
7 
2 
5 
8 
3 
6 
9 
xyz(i,j)   1   1 1.0000000000000000  
xyz(i,j)   2   1 1.0000000000000000  
xyz(i,j)   3   1 1.0000000000000000  
xyz(i,j)   1   2 1.0000000000000000  
xyz(i,j)   2   2 1.0000000000000000  
xyz(i,j)   3   2 1.0000000000000000  
xyz(i,j)   1   3 1.0000000000000000  
xyz(i,j)   2   3 1.0000000000000000  
xyz(i,j)   3   3 1.0000000000000000  

This file was compiled using GCC version 6.1.1 20160802 using the options -mtune=generic -march=x86-64 -Wall 
+1

Können Sie erklären, was Sie behoben haben? –

+0

Keine Änderungen zu sehen – user1131484

+0

ja ein bisschen Änderung in c-Code: void * verwendet und es hat funktioniert – user1131484