Navjot Singh
Navjot Singh

Reputation: 696

How to copy for the following scenario?

I have a Memory mapped file and corresponding MapViewOfFile handle. The memory mapped file will contain data in two parts:

  1. unsigned int specifying the length of actual data
  2. Actual relevant data

For e.g. if the length of my actual data is 10 characters, the memory mapped file would be like:

10
abcdefghij

where abcdefghij is the data I want and there will be a newline b/w the length number and data. I am also free to use any other delimiter if needed.

Now I want to read the unsigned int first in order to be able to read the actual data. I am thinking of memcpy but I am not sure how can I get the exact unsigned int value as I think memcpy copies character by character. How can I extract 10 as it is from the content?

Upvotes: 1

Views: 90

Answers (1)

João Paulo
João Paulo

Reputation: 6690

You can do like so:

#include "windows.h"
#include <iostream>

int main() {
    const size_t buffer_size = 4098;
    const char* name = "my_shared_memory"; //sm name
    HANDLE file = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, buffer_size, name);
    LPVOID region = MapViewOfFile(file, FILE_MAP_ALL_ACCESS, 0, 0, buffer_size);

    const char* const msg = "this is my data"; //this is the string you want to pass
    const int msg_size = strlen(msg) + 1; //this is the size of the string data with \0
    const int total_size = msg_size + sizeof(int); //the total size of your data: the size of the string and the string by itself
    char* const data = (char*)malloc(total_size); //get some memory to place this data
    ((int*)data)[0] = msg_size; //set the first part of the data with the string msg size
    memcpy(data + sizeof(int), msg, msg_size); //set the msg by it self just after the size

    CopyMemory(region, data, total_size); //put on sm

    const int retrieved_size = ((int*)region)[0]; //retrieves the size of the msg from the sm
    char* const retrieved_msg = (char*)malloc(retrieved_size); //alloc some space for receive the msg with the retrieved size
    memcpy(retrieved_msg, (char*)region + sizeof(int), retrieved_size); //set the msg in the previous allocated memory
    std::cout << retrieved_msg << std::endl; //prints the msg

    free(data);
    free(retrieved_msg);
}

In this question you have some solutions to check for endianess. Then you can use one more byte to store this information if necessary. If endianess is different, you can swap bytes.


Solution for Josh comment:

For ASCII encoded size, instead of putting on memory the size int binary encoded, you can save as if it were a string:

const int max_digits_size = 3;
char number[max_digits_size + 1];
sprintf(number, "%d", msg_size);
//your total_size is now (max_digits_size + 1) + msg_size

//first you retrieve from sm the number as string in number_memcopied var, then you convert:
const int retrieved_size = strtol(number_memcopied, NULL, 10);

Upvotes: 1

Related Questions