Интерфейс Fortran для вызова функции C, которая возвращает указатель
У меня есть функция C,
double* foofunc()
{
/* Function Body */
}
Я не знаю, как объявить интерфейс в Fortran
называть это C
функция.
Также, если указатель должен указывать на GPU device memory
как я могу определить это в Fortran
интерфейс? Нужно ли использовать DEVICE
приписывать.
Пожалуйста, используйте функции, поддерживаемые Fortran
до 2003 года.
Какие-либо предложения?
4 ответа
Поскольку у вас есть Fortran 2003, простой способ взаимодействия между Fortran и C состоит в использовании привязки ISO C. (Большинство компиляторов Fortran 95 теперь поддерживают привязку ISO C, даже если они не являются полными компиляторами Fortran 2003.) Это намного, намного лучше, чем сложные методы, предложенные в предыдущем ответе, которые были необходимы в более раннюю эпоху - это является частью языка и, следовательно, переносимым, и не зависит от компилятора и платформы. Но версия на Фортране 2003 никогда не охватывает возможности. (Следующий Fortran добавит дополнительные случаи взаимодействия с C.) Вы можете легко передать аргумент, который является указателем C - просто пропустите атрибут "value" в объявлении Fortran. Указатель на указатель нуждается в C_PTR. Я не знаю насчет указателя как функции возврата... мне придется экспериментировать, когда у меня будет время. Если вам нужно, создайте тривиальную подпрограмму на языке C, которая преобразует указатель функции, возвращаемый в аргумент, - это легко.
Переведите указатель на память устройства GPU - если у вашего компилятора нет нестандартной функции, у него не будет "DEVICE". Возможно, "изменчивый" поможет? Создать соответствующий определенный пользователем тип...
В руководстве по gfortran есть примеры в разделе "Взаимодействие с C". Поскольку это часть языка, эта документация должна помочь, даже если вы не используете gfortran.
Как сказал MSB, использовать возможности взаимодействия с Fortran 2003 C проще всего.
Просто объявите результат функции как type(c_ptr)
и преобразовать его в указатель на фортран, вызвав c_f_pointer
,
Следующий простой пример работает при компиляции с:gfortran foo.f03 foofunc.c -o foo.exe
(gfortran версия 4.5.0)
Содержание foo.f03:
program foo
use, intrinsic :: iso_c_binding, only : c_ptr, &
c_f_pointer, &
c_double
implicit none
type(c_ptr) :: c_p
real(c_double), pointer :: f_p
interface
function foofunc() bind(c)
import :: c_ptr
implicit none
type(c_ptr) :: foofunc
end function foofunc
end interface
c_p = foofunc()
call c_f_pointer(c_p, f_p)
print *, f_p
end program foo
Содержание foofunc.c:
double bar = 2;
double *foofunc()
{
return &bar;
}
Я не знаю, насколько хорошо он будет работать с указателем на память устройства GPU. Никогда не имел дело с этим.
Вы хотите вызвать функцию C из программы Fortran. Есть много способов.
Одним из способов является перевод рутины С на фортран. Если ваша C-программа длинна, сложна и хорошо протестирована, то это может оказаться нелегким вариантом для вас. Другой способ - конвертировать фортран в C. Возможно, у вас схожие проблемы.
Если вы не можете обойти проблему, как указано выше, вам придется столкнуться с проблемой, как показано ниже.
На языке программирования это называется смешанным языком программирования.
Я не знаю, какую версию какого языка и OS U используете. Поэтому вместо того, чтобы дать готовое решение, я дам вам четыре альтернативных подхода ниже. Я использовал все в реализованных приложениях. Первые два предназначены для тех, кому повезло с мощной ОС (сейчас это редкий товар). Программа работает быстро и подходит для тяжелых работ в режиме реального времени. Последние два предназначены для любой ОС, но программа работает медленно, особенно если процедура C вызывается часто. Вы также должны сделать немного больше работы по программированию во всех подходах. Также помните, что ваша функция C возвращает указатель в каждой из альтернатив.
Некоторые компиляторы фортрана (не все) позволяют вызывать нефортранскую функцию. Это требует соответствующих средств в ОС, где работают и fortran, и C. В таких случаях идентичное управление стека используется во время вызова процедуры. Прочитайте руководство для программистов на обоих языках и код соответствующим образом.
Если это невозможно, вы можете обмануть ОС, но вам нужна промежуточная функция, написанная на ассемблере. Вы вызываете подпрограмму ассемблера из fortran, а затем вызываете подпрограмму C из ассемблера и возвращаетесь в обратном порядке. Вам необходимо знать детали управления стеками всех трех компонентов, таких как Fortran, Assembler и C, и написать код для перевода стека fortran в C-стек. Это будет в рутине ассемблера.
При обоих вышеперечисленных подходах вы должны знать, как работает ваш компоновщик (или Binder), и вам, возможно, придется выполнять там некоторую дополнительную работу. В любом случае это будет тот же файл.exe, поэтому ваша программа будет работать быстро. В таких ОС любые языки, странные друг для друга, можно смешивать. Даже DLL могут быть использованы. Сложность возникает только в том случае, если библиотека времени выполнения использует функцию fortran, имеющую то же имя, что и функция C, но выполняющая различные задания. ОС, поддерживающая смешанное языковое программирование, обычно дает вам некоторые инструменты для предотвращения этого.
Если вышеупомянутые альтернативы неосуществимы, сделайте обе программы на Fortran и C как отдельные.exe и запустите обе как два параллельных процесса. (обратите внимание, что они могут быть на одном компьютере или на разных компьютерах под разными ОС даже!). Теперь всякий раз, когда вам нужно вызвать C из Фортрана, передайте все параметры и данные через любой доступный вам механизм межпроцессного взаимодействия, например, канал, сокет или что-то еще. Программа на C может возвращать данные с помощью аналогичного механизма. Обязательно добавьте соответствующий код для обработки передачи параметров через межпроцессное взаимодействие. Синхронизация двух процессов и отличение старых данных от последних данных также ваша работа. Управление стеками не требуется.
Это для тех, кто не любит стек, синхронизацию, компоновщик или все, что требует интеллекта. Программы будут работать медленнее, если программа C будет вызываться часто. Неудобно, что если программу на C нужно вызывать только один раз, то это тоже самое разумное решение! Вывод данных из фортрановой программы на диск (плоский файл или база данных). Затем вызовите программу на C для чтения из того же файла и возврата данных в фортран таким же образом. Будьте внимательны при закрытии файла перед сменой языка. Обрабатывать все ошибки в файлах вызовов ввода-вывода. Иначе ты терпишь крах.
Ваш ответ такой же, как и пункт № 1 моего ответа ( 1. Некоторые компиляторы на Фортране...). Однако вы упомянули, что "Но версия Fortran 2003 не охватывает все возможности". Это практический момент.
Программисты часто встречают цель; В любом случае проблема может возникнуть, даже если последняя версия компилятора или коннектора недоступна. Я дал проверенные альтернативы. Существует одна альтернатива для школьников, а другая - для проблем "в реальном времени". Это может занять больше времени, но что делать, пока вы не получите версию Fortran, которая отлично взаимодействует с другим языком.
Если ваши существующие отлаженные программы на Fortran и C вместе имеют длину 30000 строк, то использование новой версии компилятора в клиентской системе 2000 может снять множество других проблем. Люди потеряли больше времени с такими проблемами, чем потратили несколько лишних человеко-дней, чтобы самостоятельно написать некоторые соединители, используя общедоступные ресурсы в существующих компиляторах и ОС. Мы внедряем новый компилятор после нового тестирования всех компонентов наших приложений. Золотое правило гласит: "Работать с существующим компилятором с его известными ошибками легче, чем с его последней версией, имеющей неизвестные ошибки". Правило применимо только для больших практических задач.