2017-01-06 3 views
0

Я пытаюсь создать функцию в C, которая вызывается из Fortran. Прежде всего. Код fortran скомпилируется с помощью f77, а c скомпилирован с gcc. Оба они скомпилированы в .so библиотеки. Функция c будет считывать память на устройстве по адресу и размеру, указанному fortran. Я могу видеть адрес, и размер передается в c, но у меня возникают проблемы с заполнением данных в c-функции и возвратом его в fortran. См. Соответствующий код ниже. Мое предположение заключается в том, что в распределении памяти или в синтаксисе указателя для переменной данных есть что-то неправильное.Вызов функции C из Fortran с помощью указателей

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 
+1

Почему вы думаете, что-то не так? Что происходит? На стороне Фортрана, что такое 'memsize' и' printf' и что такое 'z'dead'', где он находится? На стороне C, почему 'uint8_t'? Почему вы не можете использовать стандартную функциональность Fortran-C? – francescalus

+0

Well mate, это в значительной степени зависит от вызывающих конвенций ... Я никогда не писал fortran-код на протяжении всей моей жизни, но теперь я попробую – DrPrItay

+0

любые сообщения об ошибках? Какие? Неверные результаты? Как они выглядят? –

ответ

2

У меня есть несколько точек в код.

Пожалуйста, поставьте компилируемый код и опишите вывод этого точного кода!

Это касается #include для стандартных заголовков, если вы хотите, чтобы люди отлаживали ваш код, упростили их, чтобы им не пришлось искать, какие строки вы пропустили, потому что они казались вам «очевидными». Просто вставьте все. Код должен компилироваться при копировании отсюда!

Даже исполняемая часть вашего кода не компилируется в моем компиляторе. Мне пришлось изменить *data на data. Вы действительно скопировали свой фактический код?

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]); 
         ^

Ваш Fortran код содержит вызов некоторой printf подпрограммы. Где это определено? Он присутствует в вашем фактическом коде? Я сомневаюсь. Скопируйте в StackOverflow всегда полный и компилируемый код.

Таким образом, после фиксации очевидного вашего настоящего кода является:

#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 

Он не откажет, но memory в Fortran содержит мусор. Это необходимо, потому что это integer, и вы рассматриваете его как int8_t. C.

Так что либо рассматривайте его как массив из четырех целых чисел в C, либо скопируйте его байтом по байту, но затем вы должны передать правильное количество байтов для копирования. Из вашего описания не ясно, какой из них является ваше намерение, так что я покажу только одну возможность:

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

Выход правильно, то:

> 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 
+0

После гораздо большего исследования я обнаружил, что на самом деле нет решения для моих целей. Решение, которое вы предоставили, было правильным и будет работать, если я не буду использовать компилятор f77. f77 не позволяет перейти от c к fortran, и с использованием кода, который вы предоставили, массив fortran всегда содержал мусор. Если бы я мог использовать f90, то решение, которое вы предоставили, будет работать. – cwheat

+0

Каждый компилятор имеет свое собственное соглашение о вызове. В принципе, все компиляторы F77 допускают это, но нет * «компилятора F77» *, существует много разных компиляторов, и вы должны изучить руководство, чтобы узнать, как это сделать должным образом. Это не F77 vs F90, это один компилятор и другой компилятор. Мое решение не является стандартным F90, оно специфично для gfortran. Нет стандартного решения F90, стандартная совместимость C-Fortran - F2003. –