Hey guys, I have two structs and I have two functions in two DLL's. DLL-A is attached to a process and collects data. When the data is requested by DLLB which is attached to a second process, DLLA maps the data for B to read.

The problem is, I cannot seem to get it to transfer structs or vectors. It transfers Integers perfectly fine but not Floats or objects/containers. Is there a way to share these across memory?

struct FontChar
{
    GLuint ID;
    GLchar Symbol;
    GLboolean LastFont;
    GLint TCount, VCount;
    struct
    {
        GLint VX[4], VY[4];
        GLint TX[4], TY[4];
    } Quad;
};

struct Model
{
    GLint SX, SY;
    GLuint Stride;
    unsigned long ID;
    GLint TriangleCount;
    GLboolean NullVertex;
    GLboolean ShowVertices;
    const GLvoid* VertexPointer;
    std::vector<Vector3D> Vertices;
};

std::vector<Model> ListOfModels;
std::vector<FontChar> ListOfFonts;

//In my communication function for DLL-A, this is the one of two cases that do not work:
case GLHook_GetModels:
{
    Data[1] = GLStatusReturned;
    Data[3] = &ListOfModels[0];
}
break;

case GLHook_Fonts:
{
    Data[1] = GLStatusReturned;
    Data[3] = &ListOfFonts[0];
}

//Finally in DLL-B:
GL_EXPORT char* GLHGetTextArea(int X1, int Y1, int X2, int Y2)
{
    int* Data = static_cast<int*>(RequestSharedMemory());
    Data[0] = GLHook_GetTextArea;
    Data[1] = GLStatusSent;
    Data[3] = X1; Data[4] = Y1;
    Data[5] = X2; Data[6] = Y2;

    if (SharedDataFetched())
    {
        return reinterpret_cast<char*>(Data[7]);
    }
    return NULL;
}

GL_EXPORT void* GLHGetModels()
{
    int* Data = static_cast<int*>(RequestSharedMemory());
    Data[0] = GLHook_GetModels;
    Data[1] = GLStatusSent;

    if (SharedDataFetched())
    {
        return reinterpret_cast<void*>(Data[3]);
    }

    return NULL;
}

Recommended Answers

All 4 Replies

It is extremely hard to have any clear idea about what the actual problem is when all there is is a few fragments of incomprehensible code.

Could you create a small test setup that reproduces the error? Like two very small DLLs with only the bare minimum functions to show what you are basically trying to do. The smallest and simplest possible code that reproduces the error (or problem). This way, we can have a clearer and more complete idea of what you are trying to accomplish. So far, from your explanation and your code, I do not understand what you are trying to do, what you are actually doing, or what problems you are encountering.

And, of course, when you are talking about a DLL or cross-modular problem, you must first ensure that all the DLLs are compiled with the exact same compiler (and version), with the exact same settings (compile options), and second, those are details you need to provide.

DLL A: This DLL gets attached to Process A and collects data. When it receives commands, it maps the data it collected so that DLL B can read it. I've left some comments in there to further explain.

struct FontChar      //A structure to hold a single character. I cut down on the size of this struct.
{
    GLuint ID;
    GLchar Symbol;         //Holds letters All 256 characters.
};

struct Model                //A structure to hold model data. I cut down on the size of this.
{
    unsigned long ID;
    const GLvoid* VertexPointer;
    std::vector<Vector3D> Vertices; //Holds all vertices.
};

void* hMapFile = NULL;             //FileMap pointer. Void* for easy casting.
std::vector<Model> ListOfModels;   //A list of all models. So an array of ModelStruct.
std::vector<FontChar> ListOfFonts; //Basically a string since it's a list of chars.


bool Initialize()       //Initializes my shared memory.
{
    if ((hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MapSize, SharedMemoryName.c_str())) == NULL)
        return false;

    if ((pData = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, MapSize)) == NULL)
    {
        CloseHandle(hMapFile);
        return false;
    }
    return true;
}

void ExecuteCommands()
{
    int* Data = static_cast<int*>(pData);    //Our File map pointer.
    if (Data[1] == GLStatusSent)            //GLStatusSent  = 1. I'm using this to set commands.
    {
        switch(Data[0])                     //Data[0] Holds the command sent.
        {
            case GLHook_GetModels:          //defined as 12.
            {
                Data[1] = GLStatusReturned; //Just for communication/synchronization. It lets the other dll know a value was returned.
                Data[3] = &ListOfModels[0]; //Data[3] is supposed to hold the list of all models. Which will be read from DLL-B.
            }
            break

            case GLHook_GetTextArea:
            {
                Data[1] = GLStatusReturned;
                std::string FontString;
                for (std::vector<FontChar>::iterator it = ListOfFonts.begin(); it != ListOfFonts.end(); ++it)
                    FontString += it->Symbol;  //Now I have a string of characters..

                CopyMemory(&Data[7], &FontString, FontString.size());  //Copy the string of chars to the memory mapping.
                //Data[7] = &ListOfFonts[0];  //This wasn't working so I made a vector first.
            }
        }
    }
}


GL_EXTERN BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            DisableThreadLibraryCalls(hinstDLL);
            return Initialize();
        }
        break;

        case DLL_PROCESS_DETACH:
        {
            return DeInitialize();   //Unmaps the shared memory and closes the handle.
        }
        break;
    }
    return TRUE;
}

DLL B: Sends commands and retrieves data which it then passes to a pascal program:

//DLL B:

struct FontChar      //A structure to hold a single character. I cut down on the size of this struct.
{
    GLuint ID;
    GLchar Symbol;         //Holds letters All 256 characters.
};

struct Model                //A structure to hold model data. I cut down on the size of this.
{
    unsigned long ID;
    const GLvoid* VertexPointer;
    std::vector<Vector3D> Vertices; //Holds all vertices.
};

void* hMapFile = NULL;             //FileMap pointer. Void* for easy casting.
std::vector<Model> ListOfModels;   //A list of all models. So an array of ModelStruct.
std::vector<FontChar> ListOfFonts; //Basically a string since it's a list of chars.


bool Initialize()       //Initializes my shared memory.
{
    if ((hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, SharedMemoryName.c_str())) == NULL)
    {
        std::cout<<"\nCould Not Open Shared Memory Map.\n";
        return false;
    }

    if ((pData = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, MapSize)) == NULL)
    {
        CloseHandle(hMapFile);
        std::cout<<"\nCould Not Map View Of File.\n";
        return false;
    }
    std::cout<<"\nInter-Process Communication Successful.\n";
    return true;
}

GL_EXPORT char* GLHGetTextArea(int X1, int Y1, int X2, int Y2)   //Asks DLL-A for Data. And returns the data it grabbed.
{
    int* Data = static_cast<int*>(RequestSharedMemory());
    Data[0] = GLHook_GetTextArea;           //The command sent. It tells DLL-A to map the data for Fonts. Aka it's asking for the list of chars.
    Data[1] = GLStatusSent;                 //It's telling it a command is sent and it will wait for a return value.
    Data[3] = X1; Data[4] = Y1;             //ignore these.
    Data[5] = X2; Data[6] = Y2;

    if (SharedDataFetched())
    {
        return reinterpret_cast<char*>(Data[7]);    //Return the data we got from DLL-A  via the Map file. It's supposed to return a string of chars.
    }
    return NULL;
}

GL_EXPORT void* GLHGetModels()      //Asks DLL-A for Data. And returns the data it grabbed.
{
    int* Data = static_cast<int*>(RequestSharedMemory());
    Data[0] = GLHook_GetModels;    //The command sent is for DLL-A's Model Data. It asks DLL-A to send over the ListOfModels.
    Data[1] = GLStatusSent;        //waits for a return value.

    if (SharedDataFetched())   //Checks if DLL-A sent returned anything via a return code. This is Data[2].
    {
        return reinterpret_cast<void*>(Data[3]);  //Returns a list of models found from DLL-A.
    }

    return NULL;
}


GL_EXTERN BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            DisableThreadLibraryCalls(hinstDLL);
            return Initialize();
        }
        break;

        case DLL_PROCESS_DETACH:
        {
            return DeInitialize();   //Unmaps the shared memory and closes the handle.
        }
        break;
    }
    return TRUE;
}


//This is just a side note, the functions are exported like this for Pascal:
char* Exports[] = {

    (char*)"GLHGetTextArea", (char*)"Function GLHGetTextArea(X1, Y1, X2, Y2: Integer): PChar;",
    (char*)"GLHGetModels", (char*)"Function GLHGetModels(): Integer;",

};

GL_EXPORT int GetPluginABIVersion()
{
    return 2;
}

GL_EXPORT int GetFunctionCount()
{
    return NumberOfExports;
}

GL_EXPORT int GetFunctionInfo(int Index, void*& Address, char*& Definition)
{
    if (Index < NumberOfExports)
    {
        Address = (void*)GetProcAddress(hInstance, Exports[Index * 2]);
        strcpy(Definition, Exports[Index * 2 + 1]);
        return Index;
    }
    return -1;
}

Now the problem is that it isn't returning. The map isn't holding the structs. I've tried using this for integers, the values return perfectly fine. But when it comes to the above with structs and vectors, it returns neither of them to DLL-B. Same problem with floats.

Two DLLs loaded like that will reside in separate address spaces. You cannot exchange pointers or any pointer-containing object (like std::vector or your Model struct) between them through a mapped file. If you put a pointer address in a mapped file from DLL-A, and try to retrieve it from DLL-B, the pointer that DLL-B obtains will be completely useless because it is a pointer into DLL-A's address space, and is thus completely meaningless in DLL-B's address space.

To send this kind of information, you'll have to send the information in its entirety, not a pointer to it. In other words, you need to copy the information that the pointers point to into the mapped file, and then reconstruct it all in DLL-B.

How would I copy that data? MSDN only shows how to send a string. Also do I have to Map and unmap every time I make a call or can I just map upon load and then unmap upon detach? For example, if I want to request an int, I'd have my DLL map upon start and cast my void* to an int* and request. Now can I cast that void* to an int again and request again? Or do I have to close the file and map and cast to a float first?

Would my file be physical? Atm, I cannot see the "Local\Object" file which I like. I don't want to have to create a physical file that I can see on the desktop but if I have to, I will.

I realize that's a lot of questions I'm asking but there isn't many tutorials for maps on windows.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.