简体   繁体   中英

Calling C function from Fortran with pointers

I am attempting to create a function in C that is called from Fortran. First things first. The fortran code is being compiled with f77, and the c is compiled with gcc. Both are compiled into .so libraries. The c function is going to read the memory on a device at an address, and size, specified by the fortran. I am able to see the address, and size being passed to the c, but I am having trouble filling the data in the c function and returning it to the fortran. See the relevant code below. My assumption is that there is something wrong in the memory allocation or pointer syntax for the data variable.

C

void copymemory_( uint32_t *addr, int *size, uint8_t *data )
{

    int i;
    printf("addr %x \n", *addr);
    printf("size %i \n", *size);

    for ( i = 0; i<*size; i++)
    {
        *data[i] = i;
        printf("memory %i \n",*data[i]);
    }

}

Fortran

integer memory(4)
call copymemory(z'dead', 4, memory)

DO i = 1,memsize
   call printf(memory(i))
END DO

I have several points to your code.

Please, supply compilable code and describe the output of that exact code!

That includes the #include for standard headers, if you want people to debug your code, make it easy for them so that they don't have to search which lines did you omit because they seemed "obvious" to you. Just paste everything. The code should compile when copied from here!

Even the executable part of your code does not compile in my compiler. I had to change the *data to data . Are you sure you copied your actual code?

cfun.c: In function ‘copymemory_’:
cfun.c:13:9: error: invalid type argument of unary ‘*’ (have ‘int’)
         *data[i] = i;
         ^
cfun.c:14:31: error: invalid type argument of unary ‘*’ (have ‘int’)
         printf("memory %i \n",*data[i]);
                           ^

Your Fortran code contains a call to some printf subroutine. Where is this defined? Is it present in your actual code? I doubt so. Please copy to StackOverflow always a complete and compilable code.

So after fixing the obvious your present code is:

#include <stdio.h>
#include <stdint.h>

void copymemory_( uint32_t *addr, int *size, uint8_t *data )
{

    int i;
    printf("addr %x \n", *addr);
    printf("size %i \n", *size);

    for ( i = 0; i<*size; i++)
    {
        data[i] = i;
        printf("memory %i \n",data[i]);
    }

}


implicit none

integer :: memsize = 4

integer memory(4)
integer i

call copymemory(z'dead', 4, memory)

DO i = 1,memsize
   print *, (memory(i))
END DO

END

It does not crash but memory in Fortran contains garbage. It has to, because it is integer and you are treating it as int8_t in C.

So either treat it as an array of four integers in C or copy it byte by byte, but then you must pass the correct number of bytes to copy. From your description it is not clear which one is your intention so I will show just one possibility:

void copymemory_( uint32_t *addr, int *size, uint32_t *data )

The output is correct then:

> gfortran-4.10 -fsanitize=address cfun.c ffun.f90 
> ./a.out 
addr dead 
size 4 
memory 0 
memory 1 
memory 2 
memory 3 
           0
           1
           2
           3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM