Mixed programming C++/Fortran linking


I have an existing project in VS2015 which creates a static library. In order to enhance the functionality in there, I am creating another pgi fortran static library (uses CUDA if relevant) which implements the necessary features.
I am adding the .lib file as “Additional Dependencies” (in Project Properties > Librarian > General) as well as the folder where it resides (“Additional Library Directories”).

However, the linker complains about unresolved external symbol.

A minimal example code is the following:

! Fortran lib.f90
subroutine my_pgi_subroutine() bind(C, name="my_pgi_subroutine")
!! some code here
end subroutine

// C++ static_lib.cpp
extern "C" void device_query_master(void);
extern "C" void __cdecl my_pgi_subroutine_(void);

extern "C" void device_query_master(void)

The message I get is the following:
error LNK2019: unresolved external symbol my_pgi_subroutine_referenced in function device_query_master

I would be grateful if you had any thoughts on that!

Hi aristos,

Since you’re using C binding with a string, the compiler will use that string for the symbol name and not name mangle (i.e. not add the underbar).

Try calling “my_pgi_subroutine();” from the C code, change the symbol name in the bind string, or remove the bind altogether.

Hope this helps,

Hi Mat,

Thanks for the advice.

It worked but I have new errors now. It complains about unresolved external symbols like pgf90* (pgf90io_print, pgf90encode_fmta etc)…
I reckon there should be some static library containing those. However, I’m afraid that once I add a .lib file, I get a cascade effect where I need to define more and more.

Is my approach correct or completely off?


I’m assuming you’re linking with the C++ compiler. In that case you do need to add the PGI Fortran runtime libraries to your link line.

The easiest way to get the list of libraries you need is to run the command “pgfortran -dryrun x.obj”. This will show you what the commands the compiler driver uses including the link command. For example on my system, the options passed to the linker are:

C:\PROGRA~1\PGI/win64/19.4/lib\pgimainmx.obj C:\PROGRA~1\PGI/win64/19.4/lib\f90main.obj -incremental:no -debug -nologo -merge:__nv_module_id=.data -merge:.nvFatBinSegment=.data "-libpath:C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/lib/x64" "-libpath:C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/ucrt/x64" "-libpath:C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64" -libpath:C:\PROGRA~1\PGI/win64/19.4/lib x.obj -out:x.exe -pdb:./x.pdb /DYNAMICBASE:NO -defaultlib:libpgmp -defaultlib:pg -defaultlib:libpgf90rtl -defaultlib:libpgf90 -defaultlib:libpgf90_rpm1 -defaultlib:libpgf902 -defaultlib:libpgf90rtl -defaultlib:libpgftnrtl -nodefaultlib:msvcrt -defaultlib:libvcruntime -defaultlib:libucrt -defaultlib:libcmt -defaultlib:libpgc -defaultlib:libnspgc -defaultlib:libpgmath -defaultlib:legacy_stdio_definitions -defaultlib:oldnames

You don’t need all of these but just the PGI runtime, so you’d add something like the following to your own link:

-libpath:C:\PROGRA~1\PGI/win64/19.4/lib /DYNAMICBASE:NO -defaultlib:libpgmp -defaultlib:pg -defaultlib:libpgf90rtl -defaultlib:libpgf90 -defaultlib:libpgf90_rpm1 -defaultlib:libpgf902 -defaultlib:libpgf90rtl -defaultlib:libpgftnrtl -defaultlib:libpgc -defaultlib:libnspgc -defaultlib:libpgmath -defaultlib:legacy_stdio_definitions -defaultlib:oldnames

Hope this helps,

I will give it a try by adding the relevant .lib files for my case. However, I may have failed to mention I am using MSVC, could this be an issue?


However, I may have failed to mention I am using MSVC, could this be an issue?

No, it should be fine.