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

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

Bond__Andrew
New Contributor I
1,312 Views

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 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
1,300 Views

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.

 

View solution in original post

7 Replies
Steve_Lionel
Honored Contributor III
1,306 Views

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
Honored Contributor III
1,301 Views

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
New Contributor I
1,277 Views

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 Kudos
Steve_Lionel
Honored Contributor III
1,267 Views

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 Kudos
Bond__Andrew
New Contributor I
1,262 Views

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 Kudos
Steve_Lionel
Honored Contributor III
1,251 Views

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

 
0 Kudos
Bond__Andrew
New Contributor I
1,244 Views

Thanks for the explanation. And for your help overall.

Andrew

0 Kudos
Reply