Шаблон extern-функции "C" для вызова функций Fortran из C ++ разных типов. - PullRequest
0 голосов
/ 01 июня 2018

У меня есть библиотека с функциями fortran, которая скомпилирована с одинарной и двойной точностью, но я не могу ничего изменить в исходном коде этой библиотеки.В идеале я бы определил внешнюю функцию как

template<typename TF> extern "C" void fortran_function(TF*)

и вызвал бы функцию (с обоими вызовами в одной и той же области видимости) как

double a[3] = { 2, 3, 4 };
fortran_function<double>(a);

float b[3] = { 2, 3, 4 };
fortran_function<float>(b);

Однако это не разрешено.Как мне решить эту проблему элегантным способом?

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Возможно, вам придется использовать препроцессор C для выполнения искажения имен на стороне C ++, но на стороне Fortran нет необходимости использовать не-Fortran инструменты для достижения необходимого искажения.Рассмотрим

! mangle.i90

subroutine mangle(x) bind(C,name='fortran_function_'// &
   trim(merge('float ','double',mykind==C_FLOAT)))
   real(mykind) x(3)
   x([2,3,1]) = x
end subroutine mangle

и

! mangle.f90

module floatmod
   use ISO_C_BINDING
   implicit none
   integer, parameter :: mykind = C_FLOAT
   contains
include 'mangle.i90'
end module floatmod

module doublemod
   use ISO_C_BINDING
   implicit none
   integer, parameter :: mykind = C_DOUBLE
   contains
include 'mangle.i90'
end module doublemod

При компиляции через gfortran -c mangle.f90 вы получите файл mangle.o с подпрограммами fortran_function_float и fortran_function_double.

0 голосов
/ 01 июня 2018

Есть очень сильные проблемы с этим требованием.C ++ допускает перегрузку для собственных функций C ++, но не для связей языка "C".Спецификации связывания [dcl.link] §6 гласит:

Не более одной функции с конкретным именем может иметь связь на языке C.

А ваша попытка шаблонирования эквивалентнаявно объявив:

extern "C" void fortran_function(double *);
extern "C" void fortran_function(float *);

Это объявило бы две разные функции со связью языка C и одним и тем же именем => явным образом запрещено стандартом C ++.

Основанием для этого является использование общей реализации name mangling для создания идентификатора функции, содержащего типы аргументов, чтобы компоновщик мог их идентифицировать.Связывание языка Си точно избегает искажения имен, чтобы обеспечить взаимодействие с функциями языка Си.Это немедленно устраняет любую возможность перегрузки.


В любом случае, вы не сможете определить функции 2 C или Fortran с одинаковыми именами и с использованием других параметров.Лучшее, что я могу себе представить, - это ручное манипулирование :

extern "C" void fortran_function_double(double *);
extern "C" void fortran_function_float(float *);

Возможно, вы могли бы использовать макросы для облегчения нескольких объявлений, но я действительно недостаточно опытен в метапрограммировании макросов ...

...