Size of a class

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I am serialising an object to a memory mapped file (using the
CreateFileMapping and MapViewOfFile p/invoke calls). These need to know the
maximum size of the "file". I can put in a "good guess" ie it won't be more
than, say, 1K, but it would be tidier to use the actaul size. Is it actually
possible to find out how big an object (or even better, a class) would be
when it is serialised (I suppose one way would be to separately serialise it
to a memory stream and get the size of the memory stream, but would that be
accurate? It's certainly not very efficient.)
 
|I am serialising an object to a memory mapped file (using the
| CreateFileMapping and MapViewOfFile p/invoke calls). These need to know
the
| maximum size of the "file". I can put in a "good guess" ie it won't be
more
| than, say, 1K, but it would be tidier to use the actaul size. Is it
actually
| possible to find out how big an object (or even better, a class) would be
| when it is serialised (I suppose one way would be to separately serialise
it
| to a memory stream and get the size of the memory stream, but would that
be
| accurate? It's certainly not very efficient.)
| --
| Dave

You'll have serialize the object to a MemoryStream anyway, why do you
consider this as being inefficient?

Willy.
 
Hmm - yes, you're absolutely right. I was using some generic routines I'd got
off the web. I've spent some time understanding them and writing my own
specific code now, and I can indeed serialise to the MemoryStream first and
get the length from that.
However, I do have a couple of problems: I'm using a MemoryMappedFile and a
couple of events for IPC. Now, writing the file in process 1 is no problem,
as above, but I'm having trouble getting process 2 to read the file.
Problem 1: when I open the file by calling CreateFileMapping with both
length parameters set to zero I get an error 87 - ERROR_INVALID_PARAMETER.
Acxcording to the documentation setting zero length should open an existing
file with its existing length. If I force it by setting the low-order length
arbitrarily to 1024 it's fine.
Problem 2: having forced the open, I then find I can't get the actual
length: GetFileSize() returns INVALID_FILE_SIZE.
Any suggestions on either or both problems would be most welcome.
 
You don't have to open the file to read the mapped data, you just have to
call OpenFileMapping followed by a call to MapViewOfFile(Ex).
MapViewOfFile can be called with an offset(low and high) of 0 and a
numberOfBytesToMap = 0, this will map the memory starting from offset 0 to
the end of the section. The sending side could pass a structure (marshaled
to unmanaged memory) like this:

struct MyData {
int size;
byte[] data;
}

where MyData.data is the serialized MemoryStream and MyData.size is the size
in bytes of the serialized stream. The 'reading' side uses the size value to
copy 'size' bytes from unmanaged memory (data) to a managed byte array that
can be wrapped by a MemoryStream to be deserialized by a binary formatter.

Willy.




| Hmm - yes, you're absolutely right. I was using some generic routines I'd
got
| off the web. I've spent some time understanding them and writing my own
| specific code now, and I can indeed serialise to the MemoryStream first
and
| get the length from that.
| However, I do have a couple of problems: I'm using a MemoryMappedFile and
a
| couple of events for IPC. Now, writing the file in process 1 is no
problem,
| as above, but I'm having trouble getting process 2 to read the file.
| Problem 1: when I open the file by calling CreateFileMapping with both
| length parameters set to zero I get an error 87 - ERROR_INVALID_PARAMETER.
| Acxcording to the documentation setting zero length should open an
existing
| file with its existing length. If I force it by setting the low-order
length
| arbitrarily to 1024 it's fine.
| Problem 2: having forced the open, I then find I can't get the actual
| length: GetFileSize() returns INVALID_FILE_SIZE.
| Any suggestions on either or both problems would be most welcome.
| --
| Dave
|
|
| "Willy Denoyette [MVP]" wrote:
|
| >
| > | > |I am serialising an object to a memory mapped file (using the
| > | CreateFileMapping and MapViewOfFile p/invoke calls). These need to
know
| > the
| > | maximum size of the "file". I can put in a "good guess" ie it won't be
| > more
| > | than, say, 1K, but it would be tidier to use the actaul size. Is it
| > actually
| > | possible to find out how big an object (or even better, a class) would
be
| > | when it is serialised (I suppose one way would be to separately
serialise
| > it
| > | to a memory stream and get the size of the memory stream, but would
that
| > be
| > | accurate? It's certainly not very efficient.)
| > | --
| > | Dave
| >
| > You'll have serialize the object to a MemoryStream anyway, why do you
| > consider this as being inefficient?
| >
| > Willy.
| >
| >
| >
 
Thanks Willy. That's what I eventually did - see my other reply - after
hunting th internet for hours. I couldn't beleive that there wasn't a
GetFileSize or equivelant that would work on a MMF. Ah well, Microsoft knows
best<g>.
--
Dave


Willy Denoyette said:
You don't have to open the file to read the mapped data, you just have to
call OpenFileMapping followed by a call to MapViewOfFile(Ex).
MapViewOfFile can be called with an offset(low and high) of 0 and a
numberOfBytesToMap = 0, this will map the memory starting from offset 0 to
the end of the section. The sending side could pass a structure (marshaled
to unmanaged memory) like this:

struct MyData {
int size;
byte[] data;
}

where MyData.data is the serialized MemoryStream and MyData.size is the size
in bytes of the serialized stream. The 'reading' side uses the size value to
copy 'size' bytes from unmanaged memory (data) to a managed byte array that
can be wrapped by a MemoryStream to be deserialized by a binary formatter.

Willy.




| Hmm - yes, you're absolutely right. I was using some generic routines I'd
got
| off the web. I've spent some time understanding them and writing my own
| specific code now, and I can indeed serialise to the MemoryStream first
and
| get the length from that.
| However, I do have a couple of problems: I'm using a MemoryMappedFile and
a
| couple of events for IPC. Now, writing the file in process 1 is no
problem,
| as above, but I'm having trouble getting process 2 to read the file.
| Problem 1: when I open the file by calling CreateFileMapping with both
| length parameters set to zero I get an error 87 - ERROR_INVALID_PARAMETER.
| Acxcording to the documentation setting zero length should open an
existing
| file with its existing length. If I force it by setting the low-order
length
| arbitrarily to 1024 it's fine.
| Problem 2: having forced the open, I then find I can't get the actual
| length: GetFileSize() returns INVALID_FILE_SIZE.
| Any suggestions on either or both problems would be most welcome.
| --
| Dave
|
|
| "Willy Denoyette [MVP]" wrote:
|
| >
| > | > |I am serialising an object to a memory mapped file (using the
| > | CreateFileMapping and MapViewOfFile p/invoke calls). These need to
know
| > the
| > | maximum size of the "file". I can put in a "good guess" ie it won't be
| > more
| > | than, say, 1K, but it would be tidier to use the actaul size. Is it
| > actually
| > | possible to find out how big an object (or even better, a class) would
be
| > | when it is serialised (I suppose one way would be to separately
serialise
| > it
| > | to a memory stream and get the size of the memory stream, but would
that
| > be
| > | accurate? It's certainly not very efficient.)
| > | --
| > | Dave
| >
| > You'll have serialize the object to a MemoryStream anyway, why do you
| > consider this as being inefficient?
| >
| > Willy.
| >
| >
| >
 
Willy
Further to my previous reply, I have solved problem 1: use OpenFileMapping
not CreateFileMapping - fairly simple!
However I have scoured the web for a solution to Problem 2 - how to find the
size of the file created and written in a different process, and there simply
does not seem to be a way of doing it (other than somehow embedding the size
in the written data). Several people have posted the question on several
forums, but no one has managed to provide an answer. If you know of one I'd
certainly like to hear it.
 
There seems to be some confusion here I guess, when you create a file
mapping you effectively allocate a memory segment backed by a file (regular
or paging file).
That means that the size of the memory segment is the size specified when
calling CreateFileMapping.
Now, when you map a view of the file, by calling MapViewOfFile, you
effectively reserve a number of bytes starting at a location relative to the
beginning of the segment (offset), with a size specified by the last
argument. That means that, nor the size of the 'file' reflects the presence
of any data, nor do you have an idea of the size of the mapped view(s).
So your only option is to include the size of the mapped view into the data
stored in the buffer, like this:

....
Marshal.WriteInt32(new IntPtr((int)pBuf), (int)ms.Length);
byte[] buff = ms.GetBuffer();
// marshal managed byte array to unmanaged memory buffer (backed by a
file).
for (int i = 0; i < ms.Length; i++ )
Marshal.WriteByte(new IntPtr((int)pBuf + sizeof(int) + i), buff);
..
// signal "data available" to readers....

Here, pBuf is the pointer to a mapped view returned by MapViewOfFile, and ms
is a MemoryStream object reference.

The reading side can read the data back using something like this:

pBuf = MapViewOfFile(handle, access , 0, 0, 0))
int len = Marshal.ReadInt32(pBuf, 0);
byte[] buff = new byte[len];
for (int i = 0; i <len; i++ )
buff = Marshal.ReadByte(new IntPtr((int)pBuf + sizeof(int)), i);
MemoryStream ms = new MemoryStream(buff);
BinaryFormatter bf = new BinaryFormatter();
Object o = bf.Deserialize(ms);
//use object o
....

Another option is to marshal a structure which include size and possible
other objects properties, but in general above is all you need.


Willy.


| Willy
| Further to my previous reply, I have solved problem 1: use OpenFileMapping
| not CreateFileMapping - fairly simple!
| However I have scoured the web for a solution to Problem 2 - how to find
the
| size of the file created and written in a different process, and there
simply
| does not seem to be a way of doing it (other than somehow embedding the
size
| in the written data). Several people have posted the question on several
| forums, but no one has managed to provide an answer. If you know of one
I'd
| certainly like to hear it.
| --
| Dave
|
|
| "Willy Denoyette [MVP]" wrote:
|
| >
| > | > |I am serialising an object to a memory mapped file (using the
| > | CreateFileMapping and MapViewOfFile p/invoke calls). These need to
know
| > the
| > | maximum size of the "file". I can put in a "good guess" ie it won't be
| > more
| > | than, say, 1K, but it would be tidier to use the actaul size. Is it
| > actually
| > | possible to find out how big an object (or even better, a class) would
be
| > | when it is serialised (I suppose one way would be to separately
serialise
| > it
| > | to a memory stream and get the size of the memory stream, but would
that
| > be
| > | accurate? It's certainly not very efficient.)
| > | --
| > | Dave
| >
| > You'll have serialize the object to a MemoryStream anyway, why do you
| > consider this as being inefficient?
| >
| > Willy.
| >
| >
| >
 
Back
Top