Here's the problem I'm trying to solve:

I've written a DLL that's used as a plugin within another program.
Within the DLL is a number of structure allocations which represent the positions of points in a mesh (over time). These allocations can be very very large.

If another instance of the main program is started and my plugin is loaded, I would like to be able to access (read) these allocated structures from the first DLL instance. I would not be changing the info in memory, I just need to read it.

I can obviously write the structure to a file in the first Instance and read that back into the second Instance's memory. But because of the size, direct access to these memory structures would be optimal.

What is the best solution to this problem?


p.s. after discussing the methodology, I'll start posting some code snippets so others can follow my learning process. I'm sure I'm not the only one that has wanted to share memory but didn't know how.

I would suggest that your DLL return an appropriate pointer to these structures? I'm not familiar with the DLL environment, but it should be possible to mark said pointer as read-only, at the least.

Instances of dll usage share code, not data. You need to create a shared memory segment by the first instances of the dll to start and make that accessible by subsequent instances as they start up. You can also make that shared memory persistent so that it stays around until the system reboots.

I have not tried it but you might try something as simple as static global memory. MS-Windows does not support shared memory segments like *nix does, unless it may have been added by the .NET framework (I don't know about that). See this link and the links in it.

Edited 5 Years Ago by Ancient Dragon: n/a

Then there is this, using the page file for shared memory:

http://msdn.microsoft.com/en-us/library/aa366551(v=vs.85).aspx

So yes, it seems that Windoze requires some sort of physical file interface for shared memory. Linux also uses a file-based approach, but then everything in Linux/Unix, including physical memory, are mapped to files, at least symbolically, if not physically.

Just making the data static in the dll will do the job. Here is a quick test program that I just finished writing to prove the application

// this is the dll. The function dllmain() is generated by the vc++ 2010 express so I did not post it here.

// mydll.cpp
#include <vector>
#include "mydll.h"



static std::vector<int> myvector;


MYDLL_API std::vector<int>& Cmydll::getvector(void)
{
	return myvector;
}

// This is the constructor of a class that has been exported.
// see mydll.h for the class definition
Cmydll::Cmydll()
{
    if( myvector.size() == 0)
    {
        for(int i = 1; i < 20; i++)
            myvector.push_back(i);
    }
	return;
}
// mydll.h
// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the MYDLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// MYDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

// This class is exported from the mydll.dll
class MYDLL_API Cmydll {
public:
	Cmydll(void);
    std::vector<int>& getvector();
	// TODO: add your methods here.
};

// Now this is the application program that uses the data in the DLL. Run two or more instances of this program and you will see each instance has the same result

#include <vector>
#include <iostream>
#include "..\\..\\mydll\\mydll\\mydll.h"
#pragma comment(lib,"..\\..\\mydll\\debug\\mydll.lib")

int main()
{
    Cmydll m;
    std::vector<int>& n = m.getvector();
    for(size_t i  = 0; i < n.size(); i++)
        std::cout << n[i] << '\n';
    return 0;
}

Edited 5 Years Ago by Ancient Dragon: n/a

Yes, the dll static variable scheme should be fine for Windows. That won't work for other (Unix/Linux) operating systems unfortunately as a static variable declared like that is not shared with other instances of the dll; only the initial value when the variable is initialized will be shared. Changes to the variable will not be.

Wow! That would be super simple.
I'll give that a try tonight.

Whether it works or not, I'll post snippet of code too.

Yes, the dll static variable scheme should be fine for Windows. That won't work for other (Unix/Linux) operating systems unfortunately as a static variable declared like that is not shared with other instances of the dll; only the initial value when the variable is initialized will be shared. Changes to the variable will not be.

DLLs are only used in MS-Windows operating system. *nix does not use DLLs, they use shared libraries instead. So AFAIK the problem is not related to *nix.

The definition of static is part of C and C++ standards, so I think it should work the same on all operating systems and compilers. However I have not tested it on only MS-Windows.

Edited 5 Years Ago by Ancient Dragon: n/a

Oh Ancient One, I use "dll" as a generic term for shared libraries. A lot of us *nixers use the term that way. Strictly speaking, you are correct, but so many people have come up from the Windows ranks that the term has stuck.

I just did the same test on Ubuntu using the same source code that I posted earlier and it worked as expected. The only changes I made was, using Code::Blocks, the mydll project was a shared library and I removed all that MYDLL_API macro stuff. Then I launched two terminals, cd's to where the testdll executable was located and ran the same program in both terminals. It produced the same output in both terminals.

Edited 5 Years Ago by Ancient Dragon: n/a

Interesting. This is news to me AD. I'll have to check that out for myself. If it works generically on Linux 2.6 kernels, it would simplify a lot of cruft for embedded systems as well as bigger boxes. Thanks for the heads-up! :-)

I just noticed this thread is in the C forum. I could have sworn it was in c++ before, which is why I posted c++ code instead of C code. In any event, making the object static changes nothing because static works pretty much the same in c as it does in c++.

hmmm, not working for me...

Declared:

static Inst*	gInstList	[MAX_INST];
static FXint	gInstCnt=0;

in the routine where instance data gets created:

// allocate memory
	if( !(inst = (Inst *)calloc(1, sizeof(Inst))) )	return;

	instList[instCnt++] = inst;
	gInstList[gInstCnt++] = inst;

So I start the program and trigger allocation in my DLL (through a button in the host app).

Then I use VC++ to start up a debugged instance of the program with a break point in BOOL WINAPI DllMain() { }.

Looking at those static variables they are all 0 in the debugged code.
I was hoping to have pointers to the allocated areas from the first instance.

Any thoughts?

Edited 5 Years Ago by GregMalick: n/a

Quoting that great programming wizard Rubberman:

Great ideas come from banging head on wall after all other ideas don't work.

Alternatives are (1) memory mapped files as previously mentioned, and (2) Windows Clipboard. This involves allocating the arrays with GlobalAlloc() instead of malloc() and putting all data into a contiguous block of global memory instead of some sort of linked list where memory is scattered.

Aloha Ancient Dragon,

I'm thinking that memory mapping will indeed be the way to go.

Interestingly, the following:

#pragma data_seg("Shared")
static Inst*	gInstList	[7]={ 0, 0, 0, 0, 0, 0, 0 };
static FXint	gInstCnt=0;
#pragma data_seg()

#pragma comment(linker, "/section:Shared,rws")

gInstCnt does appear to increment.
But the gInstList pointers cannot be evaluated.
I'm assuming that the pointers point to another Address space of the second instance which renders them unaddressable....

This article has been dead for over six months. Start a new discussion instead.