Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor I
311 Views

static variable for a derived type

Jump to solution

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

Accepted Solutions
Highlighted
Black Belt Retired Employee
202 Views

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

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran

View solution in original post

0 Kudos
17 Replies
Highlighted
Black Belt
298 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.

Highlighted
New Contributor I
294 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
Highlighted
Valued Contributor III
274 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
Highlighted
New Contributor I
252 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
Highlighted
Black Belt
212 Views

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

0 Kudos
Highlighted
New Contributor I
206 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
Highlighted
Black Belt Retired Employee
203 Views

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

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran

View solution in original post

0 Kudos
Highlighted
New Contributor I
198 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
Highlighted
New Contributor I
193 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
Highlighted
Black Belt Retired Employee
187 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
--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
Highlighted
New Contributor I
175 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
Highlighted
Valued Contributor III
155 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

 

Highlighted
Black Belt Retired Employee
138 Views

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

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
New Contributor I
128 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
Highlighted
Black Belt Retired Employee
119 Views

What didn't work?

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
New Contributor I
113 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