0

How can I allocated shared memory to a static buffer like the following but using CreateFileMapping and MapViewOfFile.

#pragma data_seg(".ABC")
__declspec (dllexport) char buffer[10000]  = {0};
#pragma data_seg()
#pragma comment(linker, "-section:.ABC,rws")

The goal is to create a static shared buffer that is shared between C++ and FORTRAN applications, like it's done when using data_seg. When creating a dynamic allocated buffer, FORTRAN gets tricky because you need to de-reference the pointer, which is also doable, but it's not what I want.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
user3716892
  • 101
  • 7
  • What is the actual question? – Andre Kampling Jun 09 '17 at 13:03
  • Are we supposed to know what `CreateFileMapping` and `MapViewOfFile` are? – Jonathan Mee Jun 09 '17 at 13:13
  • 1
    @JonathanMee: Functions of the WinAPI: [CreateFileMapping](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537(v=vs.85).aspx) and [MapViewOfFile](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366761(v=vs.85).aspx). OP: What is your goal, to share with what? Could you please provide more information? – Andre Kampling Jun 09 '17 at 13:17
  • The goal is to create a static shared buffer that is shared between C++ and FORTRAN applications like it's done when using data_seg. When creating a dynamic allocated buffer, FORTRAN gets tricky because you need to de-reference the pointer, which is also doable but it's not what I want. – user3716892 Jun 09 '17 at 14:01
  • @user3716892 what makes you think `MapViewOfFile` will be any better? You will still have a pointer to dynamically allocated memory (within the system paging file). It won't be static. – Remy Lebeau Jun 09 '17 at 15:19
  • I guess that's the problem. MapViewOfFile is dynamic and has to be de-referenced in FORTRAN to be accessed. I can continue to use shared section but this has another weird behavior. When I set the value using Visual Studio 2015 debugger, the memory shows it changed and the changed value is available to the application I'm debugging BUT the value is not viewable in other applications pointing to the same shared section. Changing the value in the compiled code works fine (viewable by both applications). – user3716892 Jun 09 '17 at 15:34
  • See this link for an example of the above problem: https://stackoverflow.com/questions/44462106/setting-a-value-in-the-debugger-of-a-shared-section – user3716892 Jun 09 '17 at 16:01
  • The other problem with a shared section is that it is insecure; if a different user is running the same program, that user's program will be sharing memory with your program. MapViewOfFileEx allows you to put the shared memory mapping at a fixed location, but that runs the risk that the location you've chosen might already be in use, and I don't know whether that will work with FORTRAN anyway. Edit: huh. Actually, that should work. I'll post an answer. – Harry Johnston Jun 09 '17 at 23:50
  • ... never mind. I thought you could free the memory already occupied by the buffer, since it is in a separate section anyway, and remap it as a view of a file mapping. This can't be done, or at least not with the supported API. (It might be possible using undocumented functions, since the Windows loader manages it somehow.) The problem is that the entire executable is loaded as a single memory allocation, which means you can't free just one section. – Harry Johnston Jun 10 '17 at 00:18
  • (Are you sure modern FORTRAN compilers don't provide any solution to this problem? There's really no way to access a dynamically-located buffer as if it were a statically-located buffer?) – Harry Johnston Jun 10 '17 at 00:20
  • ... can you reference a static buffer that is located in a DLL? – Harry Johnston Jun 10 '17 at 00:22
  • Harry Johnston, see below. Modern FORTRAN does support it but in an executable statement. – user3716892 Jun 12 '17 at 15:45

1 Answers1

1

The equivalent Win32 API calls would look like this:

SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;

HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, 10000, TEXT("ABC")); 
if (!hMapping) ... // error handling

char *buffer = (char*) MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 10000);
if (!buffer) ... // error handling

// use buffer as needed... 

UnmapViewOfFile(buffer);
CloseHandle(hMapping);

Both apps would have to call CreateFileMapping() with the same lpName value to gain access to the same mapping object in the system kernel. Whichever app calls CreateFileMapping() first will create the object, and the second app will get a handle to the existing object. Then, MapViewOfFile() maps memory access within the calling process to that object. In this way, both apps are using shared memory with each other. When one app writes data into the object, the other app will see it.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I know that's how to create a shared file mapping but the problem is that I don't want a dynamic pointer (char *buffer). Probably what I want is not possible. – user3716892 Jun 09 '17 at 15:59
  • @user: That doesn't make much sense. There is little difference between the pointer `buffer` in this answer and the `buffer` array in the question. If you absolutely need to access the file mapping object as an array, you could easily cast the pointer to a reference to an array type. Or simply index the pointer. `buffer[0] = 'A';` is legal for the pointer and the array. – IInspectable Jun 09 '17 at 18:27
  • @IInspectable: what you say is true for C and C++, but remember, the OP is asking about Fortran instead. – Remy Lebeau Jun 09 '17 at 20:51
  • If the OP is having difficulty accessing the memory from FORTRAN, why does the compile time type in C or C++ matter? It's just a block of memory. I also don't understand the significant difference between a file mapping object and a shared segment in the question. Both provide a block of memory at an address, that's only known at runtime. – IInspectable Jun 10 '17 at 09:46
  • The difference is that a buffer array in FORTRAN can be accessed through a common block as apposed to a pointer buffer which needs an execution call to cast from C. I don't want to have an execution call since I'm trying to create a precompiler that only processes variable declarations. – user3716892 Jun 10 '17 at 14:17