Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29376 讨论

Error #8809: An OPTIONAL or EXTERNAL dummy argument to a BIND(C) procedure is not interoperable

Bond__Andrew
新分销商 I
3,026 次查看

I have a function in a C++ program that calls a function in a Fortran DLL, passing a callback function to receive feedback from the Fortran DLL.

However, I have a problem linking the Fortran function into my C++ program, where it is declared as:

extern "C" { bool IMPORT FortranSetCounter(bool callback(int*)); }

In my Fortran DLL the function looks like this:

logical(c_bool) function FortranSetCounter(func) bind(c, name="FortranSetCounter") result(success)

!DEC$ ATTRIBUTES DLLEXPORT :: FortranSetCounter
implicit none
logical(c_bool) func
integer number
external func
number = 3
success = func(number)

end function

When I compile this code with Intel Fortran 19.1.3, I get to errors:

error #8809: An OPTIONAL or EXTERNAL dummy argument to a BIND(C) procedure is not interoperable

error #8812: This procedure dummy argument to the BIND(C) procedure is not interoperable. [FUNC]

If I remove "bind(c, name="FortranSetCounter")" from my function declaration, then the C++ program cannot link, since it cannot find the symbol _FortranSetCounter in the LIB file.

What am I doing wrong? And what can I do to overcome the problem.

Thanks inadvance for any help you can give me.

Andrew Bond

0 项奖励
1 解答
Steve_Lionel
名誉分销商 III
3,014 次查看

Here's a suggested rewrite:

logical(c_bool) function FortranSetCounter(func) bind(c, name="FortranSetCounter") result(success)
use, intrinsic :: iso_c_binding
!DEC$ ATTRIBUTES DLLEXPORT :: FortranSetCounter
implicit none
interface
  function func (arg) bind(C)
  import
  logical(c_bool) :: func
  integer(c_int), intent(in) :: arg
  end function func
end interface
integer(c_int) ::  number

number = 3
success = func(number)
end

 

I'll note that as of Fortran 2018 (supported in the 2021 compiler), interoperable procedures may have OPTIONAL arguments. The error message if you use EXTERNAL still mentions OPTIONAL, though, even if F18 standards checking is requested. I will report this to Intel.

 

在原帖中查看解决方案

7 回复数
Steve_Lionel
名誉分销商 III
3,020 次查看

What you're doing wrong is having the "func" argument declared EXTERNAL. An interoperable procedure requires that all its dummy arguments be interoperable, and simply declaring the function EXTERNAL doesn't do that.

What you need to do instead is replace "external func" with an interface block that declares func with bind(C), and declares its return and dummy arguments with interoperable types.

 
Steve_Lionel
名誉分销商 III
3,015 次查看

Here's a suggested rewrite:

logical(c_bool) function FortranSetCounter(func) bind(c, name="FortranSetCounter") result(success)
use, intrinsic :: iso_c_binding
!DEC$ ATTRIBUTES DLLEXPORT :: FortranSetCounter
implicit none
interface
  function func (arg) bind(C)
  import
  logical(c_bool) :: func
  integer(c_int), intent(in) :: arg
  end function func
end interface
integer(c_int) ::  number

number = 3
success = func(number)
end

 

I'll note that as of Fortran 2018 (supported in the 2021 compiler), interoperable procedures may have OPTIONAL arguments. The error message if you use EXTERNAL still mentions OPTIONAL, though, even if F18 standards checking is requested. I will report this to Intel.

 
Bond__Andrew
新分销商 I
2,991 次查看

Steve

Thank you for your prompt and very comprehensive answer - that has worked perfectly.

My initial attempt was based on an old paper that I found on the web ... obviously not quite right in terms of the syntax needed nowadays.

Again many thanks

Andrew

 

0 项奖励
Steve_Lionel
名誉分销商 III
2,981 次查看

One more thing. Since you're using logical(c_bool), be sure to compile with the /standard-semantics option (in Visual Studio, Fortran > Language > Enable Fortran 20xx semantics > Yes - the "xx" may be 03, 08 or 18 depending on your compiler version.) Otherwise, the Intel Fortran interpretation of true/false will differ from C's. 

 
0 项奖励
Bond__Andrew
新分销商 I
2,976 次查看

Steve

Another helpful tip, thanks.

I have been overcoming that issue by calls to a conversion function, c_to_f_bool(c_flag) result(f_flag), that I found on the web - quite possibly in one of your previous posts?

A compiler setting is much more elegant going forwards (since 95% of my work is in C++, with one only Fortran library). It is very difficult to switch from C++ to Fortran in quick succession - I've lost count of the number of times I forget to 'Call' subroutines in Fortran!

I found the option "Enable F2003 semantics", which I have set yo Yes. But I'm baffled that the dialog box does not say  "Enable F2018 semantics" since I am running  Intel Visual Fortran Compiler 19.1.3.311 [IA-32]. Am I missing some other setting?

Note that this Fortran library started off in Compaq Visual Fortran, so some settings may be 'old'.

Andrew

0 项奖励
Steve_Lionel
名誉分销商 III
2,965 次查看

The property was described as 2003 semantics until the oneAPI (2021) version.

 
0 项奖励
Bond__Andrew
新分销商 I
2,958 次查看

Thanks for the explanation. And for your help overall.

Andrew

0 项奖励
回复