0

So the gist is to have a static global variable that can be modified by different executables. For example I have 2 different source files including the same dll.h:

dll.h

#include <iostream>

int globalCounter = 0;

__declspec(dllexport) void incrementCounter() {
    globalCounter++;
    std::cout << globalCounter << '\n';
}

Here are 2 source files that use this dll.h:

/////////// source 1
#include "dll.h"

int main()
{
    incrementCounter();
}

////////// source 2
#include "dll.h"

int main()
{
    for (int i = 0; i < 10; i++)
        incrementCounter();
}

The 2 source files will be compiled to exes and ran. The behavior is that source 2 increments to 10 and source 1 resets to print 1. How can I make it so that first, I run source2 then source1 and source1 prints 11? If this idea is not good, then is there another way of accomplishing what I want without utilizing files? The dll nature of this project HAS to stay.

1
  • 1
    IPC is hard and with such vague requirements (use DLL, don't use files) it is very hard to suggest anything concrete. I hope you understand why code you have behave the way you described - if not you probably should start with getting understanding of that. Oct 14, 2022 at 5:31

3 Answers 3

4

There will be on instance of the global counter for each executable using the DLL. Therefore each exe will have different values.

There are different ways to do IPC (Inter process Communication), the one you are looking for might be a Shared memory. This lets two processes share a space in the memory. Be really careful if the 2 processes have the right to modify the variable because that can cause some issue...

1
  • i thought thru it and i want only one process to edit the variable and the other process will read only. Can you edit the answer to this?
    – VJZ
    Oct 14, 2022 at 11:45
2

If not files, then where is the number actually stored?

If you run process A, then quit A, and run B, then everything in memory in A has gone and is inaccessible to B.

On a Windows system, I suppose you could keep it in the registry? Does that count as "not a file" for your thinking?

2
  • I meant for the sharing of data, i dont want to open and close files to pass data between dlls.
    – VJZ
    Oct 14, 2022 at 11:46
  • 3
    "DLL" isn't the relevant unit here, the unit is "processes". Processes do not normally share memory. So the variable exists in one process, and the other process gets an entirely different variable. Even if the code that accesses it came from the same DLL.
    – pjc50
    Oct 14, 2022 at 14:28
0

The shared use of a variable is possible by using a shared data segment.

Whether this is naïve or a good idea depends, as usual, on the purpose.

For example, I use them to control a single process instance of a help program that multiple processes (of the same executable) need. This is not possible with a global semaphore or latch, so a shared variable is a simple alternative with low overhead compared to any other form of IPC.

The sharing works from a DLL and also within a specific executable file, whereby in this case the variable does not have to be exported from a DLL.

You must clearly restrict simultaneous access, e.g. using a named mutex.

Example:

dll.h

#ifdef MYDLL_EXPORTS
#   define MYDLL_API __declspec(dllexport)
#else
#   define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API extern int latchCounter;

dll.cpp

#include "dll.h"

#pragma data_seg(".shared")
int latchCounter = 0;
#pragma data_seg()
// the 'S' here is the key to mark the ".shared" data segment as shared
#pragma comment(linker, "/SECTION:.shared,RWS")

main.cpp

#include <type_traits>
#include <memory>
#include <Windows.h>
#include "dll.h"

template<auto f>
using fn_constant = std::integral_constant<decltype(f), f>;
using handle_ptr = std::unique_ptr<void, fn_constant<&CloseHandle>>;

int main() {
    // increase latchCounter
    {
        handle_ptr mx{ CreateMutex(nullptr, false, L"MyLatchCounterMutex") };
        WaitForSingleObject(mx.get(), INFINITE);
        ++latchCounter;
        ReleaseMutex(mx);
    }

    // decrease latchCounter
    {
        handle_ptr mx{ CreateMutex(nullptr, false, L"MyLatchCounterMutex") };
        WaitForSingleObject(mx.get(), INFINITE);
        if (--latchCounter == 0) {
            // do something
        }
        ReleaseMutex(mx);
    }
}

See also Phil McGahan's nice and short codeproject article on this topic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.