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

static variable for a derived type

MWind2
New Contributor III
2,075 Views

How to create a C++ equivalent of a static class variable in fortran? Would this done with a get and set like method in the derived type, if needed, a private to the module access, and, if needed, an initial value?

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
1,966 Views

You should just need BIND(C) on the FUNCTION line - the name will be downcased. What error are you seeing?

View solution in original post

0 Kudos
17 Replies
IanH
Honored Contributor II
2,062 Views

The nearest equivalent is a module variable in the same module that defined the derived type.

(The difference is simply a matter of the namespace used to access the variable - in both cases the variable is a piece of global state of the program.)

How you want to provide or control access to the variable is a separate question, driven by your requirements.

MWind2
New Contributor III
2,058 Views

This is one take on it:

 

 

module fclasses
    use, intrinsic :: iso_c_binding
    integer,private :: t1i0 = 17 
    type t1
        integer             :: id = -1 
    end type t1
    interface t1
        module procedure Constructor_t1
    end interface t1
    contains
     function Constructor_t1() result(t1x)
        type(t1) :: t1x
        !initialize variables directly
        t1x%id=t1i0+1
    end function Constructor_t1
 end module fclasses
    !
 program fstatic
    use fclasses
    implicit none
    
    ! Variables
    type(t1) :: t1v0
    ! Body of fstatic
    t1v0 = Constructor_t1()
    print *, 't1v0%id=',t1v0%id

 end program fstatic

 

 

 Now this needs thread safety and if in a dll, process safety in the increment that I did not do so far but was trying to do from something done in c++.

0 Kudos
FortranFan
Honored Contributor II
2,038 Views

Per the code as shown, it would make sense for 't1i0' to be a named constant and in which case thread safety is not an issue:

integer, parameter :: t1i0 = 17

But if a named constant is not possible and 't1i0' needs to be 'writable', then you have to consider some option external to the Fortran standard to ensure thread safety with locking the variable access.  OpenMP in the context of Intel Fortran may be an option then.

0 Kudos
MWind2
New Contributor III
2,016 Views

The static variable needs to be writable to increment, and it would need to be unique to assign an id to an instance. How does one "lock'(trying x times and/or  waiting so long to obtain) a variable in fortran and unlock when done? 

0 Kudos
IanH
Honored Contributor II
1,976 Views

Are you using OpenMP for threading, or some other approach?

0 Kudos
MWind2
New Contributor III
1,970 Views

I was not planning to use Open MP. In fact, I wanted to try and make something in a c-dll provide the number, but evidently I don't know much about interfaces. I have a cdll whose code works well:

//h
#pragma once
#ifdef CDLL_EXPORTS
#define CDLL_API __declspec(dllexport)
#else
#define CDLL_API __declspec(dllimport)
#endif

// extern "C" CDLL_API volatile long long llid;
extern "C" CDLL_API long long get_id(void);
//cpp
//extern "C" CDLL_API  volatile long long llid = -1;
volatile long long llid = -1; // "hiding"

#pragma data_seg()
#pragma comment(linker, "/Section:.sdata,RWS") 
extern "C" CDLL_API long long get_id(void) {
	// use Microsoft compiler intrinsic
	volatile long long *pllid= &llid;
	long long llx = _InterlockedIncrement64(pllid);
	return (llx);
}

and the fortran that is diving me nuts is

 program ftest_cdll
   
    USE, INTRINSIC :: ISO_C_BINDING
    implicit none
    INTERFACE
    
    integer*8 FUNCTION get_id 
    integer*8 :: id
    !
    END FUNCTION get_id
    END INTERFACE
    ! Variables
     integer(8)  :: lld = -7
    ! Body of ftest_cdll
    lld = get_id()
    print *, lld

    end program ftest_cdll

Error: error LNK2019: unresolved external symbol _GET_ID referenced in function _MAIN__

 

The integer declarations I had read should be C_LONG_LONG, but that was its own problem, etc. bind (C, name = 'get_id) causes another error.  Help with proper interface, please.

0 Kudos
Steve_Lionel
Honored Contributor III
1,967 Views

You should just need BIND(C) on the FUNCTION line - the name will be downcased. What error are you seeing?

0 Kudos
MWind2
New Contributor III
1,962 Views

 

File Type: DLL

Section contains the following exports for cdll.dll

00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names

ordinal hint RVA name

1 0 000110BE get_id = @ILT+185(_get_id)

Summary

1000 .00cfg
1000 .data
1000 .idata
1000 .msvcjmc
2000 .rdata
1000 .reloc
1000 .rsrc
1000 .sdata
6000 .text
10000 .textbss

0 Kudos
MWind2
New Contributor III
1,957 Views
program ftest_cdll
   
    USE, INTRINSIC :: ISO_C_BINDING
    implicit none
    INTERFACE
       integer*8 FUNCTION get_id() BIND(C)
        integer*8 :: id
        !
        END FUNCTION get_id
    END INTERFACE
    ! Variables
     integer(8)  :: lld = -7
    ! Body of ftest_cdll
    lld = get_id()
    print *, lld
    end program ftest_cdll

That fixed it! Thank you. 

0 Kudos
Steve_Lionel
Honored Contributor III
1,951 Views

Let me suggest a modification:

program ftest_cdll
   
    USE, INTRINSIC :: ISO_C_BINDING
    implicit none
    INTERFACE
       IMPORT
        integer(C_LONG_LONG) FUNCTION get_id() BIND(C)
        integer(C_LONG_LONG) :: id  ! This is unused?
        !
        END FUNCTION get_id
    END INTERFACE
    ! Variables
     integer(C_LONG_LONG)  :: lld = -7
    ! Body of ftest_cdll
    lld = get_id()
    print *, lld
    end program ftest_cdll
MWind2
New Contributor III
1,939 Views

I get 

2>D:\c\vs2019\ftest\ftest_cdll1\ftest_cdll1.f90(20): error #8041: The IMPORT statement is not positioned correctly within the scoping unit.
2>D:\c\vs2019\ftest\ftest_cdll1\ftest_cdll1.f90(21): error #6218: This statement is positioned incorrectly and/or has syntax errors.
2>D:\c\vs2019\ftest\ftest_cdll1\ftest_cdll1.f90(22): error #6702: END statement confusion.
2>D:\c\vs2019\ftest\ftest_cdll1\ftest_cdll1.f90(22): error #6758: This name is invalid; if a name is present, it must match the corresponding interface body name. [GET_ID]
2>D:\c\vs2019\ftest\ftest_cdll1\ftest_cdll1.f90(27): error #6404: This name does not have a type, and must have an explicit type. [GET_ID]
2>compilation aborted for D:\c\vs2019\ftest\ftest_cdll1\ftest_cdll1.f90 (code 1)

when using 

    program ftest_cdll1

    USE, INTRINSIC :: ISO_C_BINDING
    implicit none
    INTERFACE
       IMPORT
        integer(C_LONG_LONG) FUNCTION get_id() BIND(C)
        END FUNCTION get_id
    END INTERFACE
    ! Variables
     integer(C_LONG_LONG)  :: lld = -7
    ! Body of ftest_cdll1
    lld = get_id()
    print *, lld
    
    end program ftest_cdll1

 

0 Kudos
andrew_4619
Honored Contributor II
1,919 Views

This variant would compile.

    program ftest_cdll1
    
    USE, INTRINSIC :: ISO_C_BINDING
    implicit none
    INTERFACE
        FUNCTION get_id() BIND(C)
            IMPORT
            integer(C_LONG_LONG) :: get_id
        END FUNCTION get_id
    END INTERFACE
    ! Variables
     integer(C_LONG_LONG)  :: lld = -7
    ! Body of ftest_cdll1
    lld = get_id()
    print *, lld

 

Steve_Lionel
Honored Contributor III
1,902 Views

Sorry - that's what I get for not test compiling it.

0 Kudos
MWind2
New Contributor III
1,892 Views

I could not get it to work with IMPORT and I suspected the function lacking args but only returning a C_LONG_LONG might have something to do with it. 

0 Kudos
Steve_Lionel
Honored Contributor III
1,883 Views
0 Kudos
MWind2
New Contributor III
1,877 Views

andrew_4619 code  works. IMPORT after FUNCTION, not before, and C_LONG_LONG(1/2) works there when it produced error before.

 program ftest_cdll1
    
    USE, INTRINSIC :: ISO_C_BINDING
    implicit none
    INTERFACE
        FUNCTION get_id() BIND(C)
            IMPORT
            integer(C_LONG_LONG) :: get_id
        END FUNCTION get_id
    END INTERFACE
    ! Variables
     integer(C_LONG_LONG)  :: lld = -7
    ! Body of ftest_cdll1
    lld = get_id()
    print *, lld
0 Kudos
Reply