2013-05-02 2 views
1

У меня есть основная программа в Fortran. Я использую Intel Visual Fortran XE 2011 на Visual Studio 2010. Я хотел бы использовать функцию, которая закодирована в C++. Функция, которую я использую, заключается в получении нескольких массивов (входных данных - из основной программы fortran) и их использования для формирования выходного массива (который должен быть возвращен основной программе fortran). Я предпринял следующие шаги:Передача массива из fortran в функцию C++

1) Я создал проект Fortran с основной программой и модулем Fortran, и я установил его как «проект запуска».

2) Я создал проект C++ типа «статическая библиотека».

3) Я добавил $(IFORT_COMPILERvv)\compiler\lib\ia32, как описано здесь http://software.intel.com/en-us/articles/configuring-visual-studio-for-mixed-language-applications

статическая библиотека C++ строится без проблем. Ошибки, которые я получаю, касаются объявления переменных real(8) в программе fortran.

я получаю следующие две ошибки для всех действительных (8) деклараций, то есть 6 ошибок в общей сложности:

ошибка # 5082: Ошибка синтаксиса, найден '(' когда ожидается один из: ::% ЗАПОЛНЕНИЕМ , ТИП BYTE ХАРАКТЕР КЛАСС DOUBLE DOUBLECOMPLEX DOUBLEPRECISION ...

ошибка # 5082: ошибка синтаксиса, нашел '::', когда ожидает одно из следующего: (*, [/ =>

Вот код, который я использовал:

Главная Fortran Программа:

Program Fort_call_C 

use iso_c_binding 

implicit none 

interface 

    subroutine vec_sum_c(a,b,c) bind (C, name = "vec_sum_c") 

     use iso_c_binding 

     implicit none 

     real(8) (c_double), intent (in), dimension (*) :: a,b 
     real(8) (c_double), intent (out), dimension (*) :: c 

    end subroutine get_filled_ar 

end interface 

integer:: i 
integer (c_int)::m 
real(8)(c_double),dimension(:):: a, b, c 

open(unit=10, file="input_arrays.txt",status="unknown") 
read(10,*) m 
allocate(a(m),b(m),c(m)) 

do i=1,m 
    read(10,*)a(i),b(i) 
end do 
close(10) 

call vec_sum_c(m,a,b,c) 

do i=1,m 
    print*, c(i) 
end do 

pause 

end program 

А функция С ++:

extern"C" void vec_sum_c(int *m, double *a, double *b, double *c){ 
    int mm = *m; 
    for(int i=0;i<=m-1;i++){ 
     c[i]=a[i]+b[i]; 
    } 
} 

Может кто-нибудь, пожалуйста, помогите мне с этим вопросом? И, пожалуйста, дайте мне знать, если идея отправки целого массива из программы fortran в подпрограмму C++ является безопасной или проблематичной (лучше быть избегаемой) попыткой?

ответ

2

Ваш синтаксис Fortran отсутствует. У вас есть настоящий вид дважды. Попробуйте

REAL(C_DOUBLE), INTENT(IN), DIMENSION(*) :: a, b 

т.д.

C_DOUBLE является именованной константой. Это имеет значение 8 с этим процессором.

также:

  • вам не хватает аргумент m в Fortran интерфейса тела для функции C.
  • вы передумали имя подпрограммы в корпусе интерфейса Fortran между оператором открытия и закрытия!
  • Ваш цикл C++ для менее чем равного сравнивается с m, который, вероятно, должен быть mm.

В этой манере нет неотъемлемой проблемы при отправке целых массивов.

+0

Большое спасибо за ваш полный ответ. Теперь, когда я сделал все эти изменения, я получаю новую ошибку, которая читает: «ошибка # 8520: аргумент массива BIND (C) должен быть явным форматом или предполагаемым размером. [A]« и те же ошибки для [B] и [C]. Означает ли это, что я не могу использовать распределяемые массивы при связывании с C? потому что я уверен, что видел образцы, где было сделано то же самое. Любая подсказка? Спасибо – user2341616

+0

Вы, должно быть, изменили объявления аргументов из того, что показано в коде в вашем вопросе. Использование аргументов с возможностью сопоставления или отложенной фигуры с функциями BIND (C) требует компилятора Fortran 201X, где X, вероятно,> = 5. ifort еще не является таким компилятором. Возможно, попробуйте еще раз через пару лет. – IanH

+0

спасибо за ваш ответ. Мне удалось решить проблему. Еще один вопрос. Если я хочу передать скалярное значение (число), полученное в процедуре C++, в fortran, как это сделать? (например, в приведенном выше коде, предположим, что я хочу изменить значение m в функции C++ и отправить его обратно в fortran.) спасибо – user2341616

0

Мне удалось передать значение переменной из функции C в функцию fortran.

Я здесь вставили два исходных файлов, а именно main.c и fortran.f Вы можете использовать эти два файла в Microsoft Visual Studio 10. После того, как делает все настройки в визуальной студии, как предложено в странице http://software.intel.com/en-us/articles/configuring-visual-studio-for-mixed-language-applications, что вам нужно сделать другое изменение как;

  1. перейти к свойству проекта статической библиотеки C/C++;
  2. перейти на C/C++
  3. перейти к генерации кода
  4. установить Runtime библиотеки в многопоточных Debug (/ МПД)

теперь вы можете построить программу ....

main.c:

#include <stdio.h> 
#include <malloc.h> 

void testc(double **pa, double **p) 
{ 
double b; 
double *a, *c; 
int m; 

c = (double*) malloc(sizeof(double)); 
*c = 10; 

*p = c; 

a = (double*) malloc(sizeof(double)*5); 
a[0]=1.23; 
    a[1]=2.46; 
a[2]=3.69; 
a[3]=4.11; 
a[4]=7.21; 
*pa=a; 
for (m=0;m<5;m++) 
{ 
    b=a[m]; 
    b=b+1.0; 
    a[m]=b; 
    } 
} 

fortran.f:

program test 
    use iso_c_binding 
    implicit none 
interface 
    subroutine testc(pa, m) bind(c) 
    use iso_c_binding 
    type(c_ptr):: m 
    type(c_ptr):: pa 
    end subroutine testc 
    end interface 

    type(c_ptr) :: pa 
    type(c_ptr) :: m 
    real(c_double),pointer::fpa(:) 
    real(c_double),pointer::fm(:) 

    call testc(pa,m) 
    call c_f_pointer(pa, fpa, [5]) 
    call c_f_pointer(m, fm, [1]) 
    print *, fm(1) 
    print*, fpa(1) 
    pause 

end program test 
Смежные вопросы