簡體   English   中英

模板化一個外部“ C”函數,以使用不同類型從C ++調用Fortran函數

[英]Template an extern “C” function to call Fortran functions from C++ with different types

我有一個帶有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);

但是,這是不允許的。 如何以一種優雅的方式解決這個問題?

此要求存在非常強烈的問題。 C ++確實允許對本機C ++函數進行重載,但不允許對“ C”語言鏈接進行重載。 鏈接規范[dcl.link]§6說:

具有特定名稱的函數最多可以具有C語言鏈接。

而您的模板嘗試等同於顯式聲明:

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

這將聲明兩個具有C語言鏈接的不同功能,並且C ++標准明確禁止使用相同的名稱=>。

其基本原理是,通用實現使用名稱修飾來構建函數標識符,該函數標識符包含用於鏈接器能夠識別它們的參數類型。 C語言鏈接恰好避免了名稱混用,以允許與C語言功能進行接口。 這立即消除了任何超載的可能性。


無論如何,您將無法使用相同的名稱和使用不同的參數來定義2 C或Fortran函數。 我能想象的最好的辦法是手動操作

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

也許您可以使用宏來簡化多個聲明,但是我真的對宏元編程還不夠熟練。

您可能必須使用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編譯時,您將得到一個包含子例程fortran_function_floatfortran_function_doublemangle.o文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM