- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should just need BIND(C) on the FUNCTION line - the name will be downcased. What error are you seeing?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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++.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
And Lock routines
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Are you using OpenMP for threading, or some other approach?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should just need BIND(C) on the FUNCTION line - the name will be downcased. What error are you seeing?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry - that's what I get for not test compiling it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page