Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29281 Discussions

Linker errors when calling a C++ routines from Fortran

mford78
Beginner
904 Views

I am sure that my error is a trivial one here, but I am at a loss for what I am doing wrong.  I want to test returning a struct from C++ to my Fortran code, but I can't even get the test program to link correctly and I am hoping someone can offer up advice.  My test solution was set up in VS2013, with a Fortran program, and a C++ DLL.  The C++ is as follows:

// Win32Project1.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

struct interop_type {
	int i;
	double j;
};
extern "C" {
	__declspec(dllexport) interop_type __stdcall _CPP_func(int* arg) {
		interop_type ret_val;

		ret_val.i = *arg * 4;
		ret_val.j = *arg / 2.0;

		return ret_val;
	}
}

And the Fortran that I want to call this function from is:

program FortranCPPInterop
    implicit none
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, ALIAS: 'CPP_func' :: CPP_func    
    type inter_op
        integer :: i
        double precision :: j
    end type inter_op
    
    TYPE(inter_op) :: test, CPP_func
    
    test = CPP_func( 3)
    
    print*, test%i
    print*, test%j
    
end program

When I attempt to build, I get the following error:
1>Source1.obj : error LNK2019: unresolved external symbol __imp_CPP_func referenced in function _MAIN__

Now, I have added the library (.lib) file created by the C++ side of the world as a library to be specifically included in the Fortran Linker options, and I have set the additional include paths for libraries in the Linker option to include the containing directory as well.  Can someone point to the mistake I am making?  Thanks!

0 Kudos
3 Replies
mford78
Beginner
904 Views

I found that I needed (or at least, this made it work) an explicit interface definition in the Fortran file.  The following works when returning a simple data type:

program FortranCPPInterop
    interface
        function CPP_func(ARG)
        !DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:'_CPP_func' :: CPP_func
        !DEC$ ATTRIBUTES REFERENCE :: ARG
        integer :: CPP_func
        integer ARG
        end function CPP_func
    end interface    
      
    integer j
    j = CPP_func( 3)
    
    print*, j
    
end program

 

0 Kudos
Amanda_S_Intel
Employee
904 Views

Thanks for the info. We have a Fortran-Calls-C sample that demonstrates the use of BIND and it's installed with the compiler (default location): C:\Program Files (x86)\Intel\Composer XE 2015\Samples\en_US\Fortran\MixedLanguage.zip. Just though I'd mention that in case it helps others as well.

0 Kudos
Steven_L_Intel1
Employee
904 Views

For your linker error, you indeed needed to link against the .lib created when the C++ DLL was built. As you discovered, use of ATTRIBUTES STDCALL also makes the default pass-by-value, so you needed REFERENCE.

Is there a reason you are using STDCALL? What you have works but it's simpler if you stick to the default calling mechanism. I'll also comment that if you're calling a routine, you don't have to use DLLIMPORT. (A data reference to a DLL does require that.)

0 Kudos
Reply