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

Mixed language module usage

dajum
Novice
828 Views

I'm trying to reference variables from a module in a c language routine. I'm using the format specified here:

https://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/2011Update/fortran/lin/bldaps_for/common/bldaps_use_modmlang.htm

Is there something else I need to do during linking to make this happen?  I get an error from my compile and link commands:

Starting compile and link
ifort /Qopenmp-report2 /Qopenmp /integer_size:64 /real_size:64 /fpe:0 /names:lowercase /iface:cref /module:..\..\..\x64\Current /MT /libs:dll /iface:mixed_
str_len_arg /include:..\..\..\include /include:..\..\..\include\fluint /include:..\..\..\proces /assume:byterecl /extend_source:132 /O3 /list /traceback /I
NCREMENTAL:NO

Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.3.202 Build 20140422
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:astap.exe
-subsystem:console
-incremental:no
-defaultlib:libiomp5md.lib
-nodefaultlib:vcomp.lib
-nodefaultlib:vcompd.lib
/LIBPATH:..\..\..\DLLs_x64
SaveSetWriter.lib
..\..\..\x64\procesCur.lib
..\..\..\x64\utilityCur.lib
multicalc.lib
tdsubproc.lib
statwin.lib
sfmatlab.lib
savesetwriter.lib
/STACK:1000000000
/MAP
/MANIFEST
/NODEFAULTLIB:msvcrt.lib
/NODEFAULTLIB:dfordll.lib
/NODEFAULTLIB:msvcrtd.lib
/NODEFAULTLIB:dfor.lib
/DEBUG
/LIBPATH:..\..\..\DLLs_x64
SaveSetWriter.lib
..\..\..\x64\procesCur.lib
..\..\..\x64\utilityCur.lib
multicalc.lib
tdsubproc.lib
statwin.lib
sfmatlab.lib
savesetwriter.lib
/STACK:1000000000
/MAP
/MANIFEST
/NODEFAULTLIB:msvcrt.lib
/NODEFAULTLIB:dfordll.lib
/NODEFAULTLIB:msvcrtd.lib
/NODEFAULTLIB:dfor.lib
/DEBUG
astap.obj
procesCur.lib(supportp.obj) : error LNK2001: unresolved external symbol LUMP_MOD_mp_LTYPE
astap.exe : fatal error LNK1120: 1 unresolved externals

 

LUMP_MOD is the module and LTYPE is the variable name

My C declaration is:
extern __int64 LUMP_MOD_mp_LTYPE[];

My fortran declaration is (note the compile arguments make all variables 64 bits)
      MODULE LUMP_MOD
      INTEGER,ALLOCATABLE :: LTYPE(:)

Thanks!

0 Kudos
7 Replies
Steven_L_Intel1
Employee
828 Views

Ditch the /names:lowercase and /iface:cref. Use the C interoperability features of the language to control names and argument passing.

0 Kudos
dajum
Novice
828 Views

non-trivial to implement I think (we support multiple fortran compilers).  Is there a way to find what the symbol name is as it stands?  I open .lib and .obj files in an editor to find routine names easily enough.  I wasn't able to do that with the .mod files. 

0 Kudos
reinhold-bader
New Contributor II
828 Views

Especially if you need to support multiple compilers, you will want to use a portable way to access the Fortran global from C. Name mangling of module entities is done differently by different compilers.

Unfortunately, while the C interop features support mapping of global array variables if the size is fixed at compile time, this is not the case for ALLOCATABLE entities. However, you can construct an accessor function that provides the address. The following should work:

Fortran module:

module mod_glob
  use, intrinsic :: iso_c_binding
  implicit none
  
  integer(c_int), allocatable, target :: a(:) ! target attribute needed for c_loc invocation
  integer(c_size_t), parameter :: size = 7
contains
  subroutine return_moddat(dat, sz) BIND(C)
    type(c_ptr) :: dat
    integer(c_size_t) :: sz
    integer :: i
    dat = c_null_ptr
    sz = 0
    if (allocated(a)) then
       dat = c_loc(a)
       sz = size(a)
    end if 
  end subroutine return_moddat
end module mod_glob

 

C program that accesses the module variable:

void return_moddat(int **dat, size_t *sz);

int main() {
  int *dat;
  size_t sz, i;
  // call some other function that allocates the module variable
  return_moddat(&dat, &sz);
  for (i=0; i<sz; i++) {
      printf("i, a: %i  %i\n",i,dat);
  }
}

Cheers

Reinhold

0 Kudos
andrew_4619
Honored Contributor III
828 Views

dajum wrote:

non-trivial to implement I think (we support multiple fortran compilers).  Is there a way to find what the symbol name is as it stands?  I open .lib and .obj files in an editor to find routine names easily enough.  I wasn't able to do that with the .mod files. 

I'm not sure I get your point. The point of the C interoperability features is to  enable mixed-language programming in a more portable manner an it is part of standard fortran. This surely makes supporting multiple compilers/platforms easier?

 

 

0 Kudos
Steven_L_Intel1
Employee
828 Views

Your problem is not with the.mod files - those are read by the Fortran compiler only. Doing  "dumpbin -symbols" on the .lib will give you the global symbol names. You really should use the F2003 standard syntax for specifying C names for module variables and procedures - it is portable.

0 Kudos
mecej4
Honored Contributor III
828 Views

dajum wrote:

non-trivial to implement I think

True, but this is a one-time effort (to port from a fixed name decoration system to the C-interop version). You have to assess whether the effort is justifiable.

(we support multiple fortran compilers).  Is there a way to find what the symbol name is as it stands?  I open .lib and .obj files in an editor to find routine names easily enough.  I wasn't able to do that with the .mod files.

The module files from one compiler are probably unintelligible to any other compiler. If you have to support a number of Fortran compilers, you can either distribute compiler-specific module files, or provide the source code to generate the .mod files (this works esp. for interfaces). However, there is little need to try to parse the .mod files.

The advantage from using C-interoperability is that MS C is, de-facto, the standard for the Windows OSes, as is GCC for Linux. The Intel Fortran compiler on each platform knows about the "companion C processor" and emits symbols compatible with that C processor.

0 Kudos
dajum
Novice
828 Views

Thanks for the help.  Got it working now. 

I want to switch to using the more standard name specifiers, but with 5000+ routines,  200+ interfacing functions, and thousands of users working with what works now,  changes happen slowly.
 

0 Kudos
Reply