[Contents] [TitleIndex] [WordIndex

Calling a COMMON from C and fortran on Windows

Fortran 77 has no global variables, i.e. variables that are shared among several program units (subroutines). We can use a common block. This is a way to specify that certain variables should be shared among certain subroutines. But in general, the use of common blocks should be minimized.

On windows, with Microsoft Visual Studio, to have a compatible version between F2C and Intel fortran , you can not export COMMON from fortran. You need to import common from C.

A little example :

unzip common_fortran_c.zip

launch scilab

exec builder.sce

exec loader.sce

In this example, mycommon is defined in C (common-c.c) and used by C and fortran.

common.f

c =================================
        subroutine getmycommon(a)
c =================================
c
Cc (DLL Intel Fortran)
cDEC$ ATTRIBUTES DLLIMPORT:: /mycommon/
c
                integer v
                common /mycommon/ v
                integer a
c =================================
                a = v
        end
c =================================

To import symbol of a common in intel fortran, you need to use "cDEC$ ATTRIBUTES DLLIMPORT:: /mycommon/".

To import symbol of a common with F2C, you need to declare a environment variable 'F2C_IMPORT_COMMON'

In this case f2c will use -E option: (declare uninitialized COMMON to be Extern (overridably defined in f2c.h as extern).

see http://www.netlib.org/f2c/f2c.1

builder_fortran.sce

// This is the builder.sce
// must be run from this directory
ilib_name  = 'libcommonf'               // interface library name

// objects files
files = ['common.f' ];

this_path = get_absolute_file_path('builder_fortran.sce');

libs  = [this_path + '../c/libcommonc']                                 // other libs needed for linking

table =['commonf','getmycommon_'];

if getos() == "Windows" then
  if (findmsifortcompiler() == 'unknown') then
        // F2C used
        setenv('F2C_IMPORT_COMMON','YES');
  end
end

// do not modify below
// ----------------------------------------------
ilib_build(ilib_name,table,files,libs);

common-c.h

/*--------------------------------------------------------------------------*/
#include "machine.h" /* C2F */
/*--------------------------------------------------------------------------*/
#ifdef COMMON_EXPORT
        #define my_export __declspec (dllexport)
#else
        #define my_export __declspec (dllimport)
#endif
/*--------------------------------------------------------------------------*/
typedef struct
{
        int v;
} MYCOMMON_struct;
/*--------------------------------------------------------------------------*/
my_export MYCOMMON_struct C2F(mycommon);
/*--------------------------------------------------------------------------*/

common-c.c

/*--------------------------------------------------------------------------*/
#define COMMON_EXPORT
#include "common-c.h"
/*--------------------------------------------------------------------------*/
void init_mycommon(void)
{
        C2F(mycommon).v = 666;
}
/*--------------------------------------------------------------------------*/

call_common.c

/*--------------------------------------------------------------------------*/
#include "stack-c.h"
#include "sciprint.h"
#include "../../src/c/common-c.h"
/*--------------------------------------------------------------------------*/
extern int F2C(getmycommon)(int *a);
extern void init_mycommon(void);
/*--------------------------------------------------------------------------*/
int sci_call_common(char *fname)
{
        int a = 0;
        int b = 0;

        init_mycommon();

        C2F(getmycommon)(&a);
        sciprint("mycommon.v from fortran: %d\n",a);

        b = C2F(mycommon).v;
        sciprint("mycommon.v from c: %d\n",b);

        LhsVar(1) = 0;

        return 0;
}
/*--------------------------------------------------------------------------*/

-->call_common();
mycommon.v from fortran: 666
mycommon.v from c: 666

2022-09-08 09:26