Question about unsafe code

  • Thread starter Thread starter Ray Z
  • Start date Start date
R

Ray Z

hi, there
I have a question about unsafe code. The following is my code:

private byte [] a = new byte [100];
private System.IntPtr b;
unsafe private Aa()
{
fixed (void * p = a)
{
b = new IntPtr(p);
}
}

my question is, after some time, the GC maybe change the position of a, will
GC change b in same time? and, in the following code, after Aa(), GC will
delete a, will GC delete the memory in same time. in another word, could we
access the memory through b?

private System.IntPtr b;
unsafe private Aa()
{
byte [] a = new byte [100];
fixed (void * p = a)
{
b = new IntPtr(p);
}
}

Thanks.

Ray
 
Ray,

I don't think the code will get you the result you want, as the array could
be relocated by the GC, which would make your IntPtr invalid.

Can you explain what you're trying to do?

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Ray,

The fixed keyword in C# will only "pins" the managed variable during the
execution of statement:
fixed
{
statement;
}

After the fixed paragraph, the GC will remove the managed memory that has
no managed reference point to.
In your program, after the fixed paragraph, there is only unmanaged pointer
points to the managed byte array, so the address the variable b points to
is invalid.

Hope this helps,
Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| From: "Ray Z" <[email protected]>
| Subject: Question about unsafe code
| Date: Fri, 31 Oct 2003 17:25:52 -0500
| Lines: 33
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.3790.0
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
| Message-ID: <#[email protected]>
| Newsgroups: microsoft.public.dotnet.languages.csharp
| NNTP-Posting-Host: x42071bc2.ip.e-nt.net 66.7.27.194
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP10.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:195861
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| hi, there
| I have a question about unsafe code. The following is my code:
|
| private byte [] a = new byte [100];
| private System.IntPtr b;
| unsafe private Aa()
| {
| fixed (void * p = a)
| {
| b = new IntPtr(p);
| }
| }
|
| my question is, after some time, the GC maybe change the position of a,
will
| GC change b in same time? and, in the following code, after Aa(), GC will
| delete a, will GC delete the memory in same time. in another word, could
we
| access the memory through b?
|
| private System.IntPtr b;
| unsafe private Aa()
| {
| byte [] a = new byte [100];
| fixed (void * p = a)
| {
| b = new IntPtr(p);
| }
| }
|
| Thanks.
|
| Ray
|
|
|
 
I want design a memory pool component. It can use IntPtr to "remember" a
block of memory. I use IntPtr because the memory can come from a byte *
pointer (come from COM) or byte[]. I want to write a function called
attach(IntPtr pMem) to input the memory. Maybe I should define the function
in this way Attach(Object pMem)?
 
Assuming you can't regenerate the pointer at use time(unlikely), you may
want to consider explicity allocation and deallocation instead of using a
byte buffer. Accept the byte buffer passed in, copy it to a new, unmanaged
buffer, and maintain a pointer to that.

You can use Marshal.AllocHGlobal() to allocate unmanaged memory blocks,
IIRC. However make sure you implement IDisposable and a finalizer so that
the memory block is always destroyed as soon as possible(hopefully when
disposed, atworst via the finalizer).
Ray Z said:
I want design a memory pool component. It can use IntPtr to "remember" a
block of memory. I use IntPtr because the memory can come from a byte *
pointer (come from COM) or byte[]. I want to write a function called
attach(IntPtr pMem) to input the memory. Maybe I should define the function
in this way Attach(Object pMem)?

Ray Z said:
hi, there
I have a question about unsafe code. The following is my code:

private byte [] a = new byte [100];
private System.IntPtr b;
unsafe private Aa()
{
fixed (void * p = a)
{
b = new IntPtr(p);
}
}

my question is, after some time, the GC maybe change the position of a, will
GC change b in same time? and, in the following code, after Aa(), GC will
delete a, will GC delete the memory in same time. in another word, could we
access the memory through b?

private System.IntPtr b;
unsafe private Aa()
{
byte [] a = new byte [100];
fixed (void * p = a)
{
b = new IntPtr(p);
}
}

Thanks.

Ray
 
Thanks all.
I think I did not make my question clear.
I am going to write a MemoryPool which can manage a block memory to hold
image data. I'd like seperate the whole block into a few small pieces(double
buffer). I will put lock in every pieces. I can not use the Daniel's
solution because the memory block is pretty big. I want to use IntPtr
because I want to accept different type (byte, short and int)memory
referrence (or pointer). For examle, user already define a int [] Var1, and
read image data (32 bits color format) from a file. he can attach Var1 to
the pool. and, when he want to process the Red color data in the data, he
can then get the byte[]Var2 (reference of same address of Var1) from the
pool.. In c#, looks we can not directly conver a int[] to a byte[]. And, in
some case, the pool need accept void*.

Ray
 
I think you will have trouble with that approach.

There is no way for you to persistantly fix/pin managed objects in C#. Fixed
objects have a big impact on the GC, and keeping them around would be bad.

If you really want to do this sort of thing, you should consider doing your
own memory allocation by calling into the Win32 memory apis yourself. You
should be able to take in arrays of whatever type you want, lock them, and
then copy stuff around as you wish.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Thanks, Eric
Could you tell me is there any way to conver a byte[] to int []? Or, in
another approach, if I alloc a block of memory use Win32 API, could I conver
it to a byte[] without memory copy. I am working on image processing, copy
memory again and again is unacceptable.

Eric Gunnerson said:
I think you will have trouble with that approach.

There is no way for you to persistantly fix/pin managed objects in C#. Fixed
objects have a big impact on the GC, and keeping them around would be bad.

If you really want to do this sort of thing, you should consider doing your
own memory allocation by calling into the Win32 memory apis yourself. You
should be able to take in arrays of whatever type you want, lock them, and
then copy stuff around as you wish.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
Ray Z said:
Thanks all.
I think I did not make my question clear.
I am going to write a MemoryPool which can manage a block memory to hold
image data. I'd like seperate the whole block into a few small pieces(double
buffer). I will put lock in every pieces. I can not use the Daniel's
solution because the memory block is pretty big. I want to use IntPtr
because I want to accept different type (byte, short and int)memory
referrence (or pointer). For examle, user already define a int [] Var1, and
read image data (32 bits color format) from a file. he can attach Var1 to
the pool. and, when he want to process the Red color data in the data, he
can then get the byte[]Var2 (reference of same address of Var1) from the
pool.. In c#, looks we can not directly conver a int[] to a byte[]. And, in
some case, the pool need accept void*.

Ray
 
Here is a raw example with some ideas for you. If this does not help,
please explain in more detail what your after. Cheers!
--William Stacey, MVP

private void button34_Click(object sender, System.EventArgs e)
{
int numInts = 5;
int numBytes = numInts * 4;
TestAlloc ta = new TestAlloc(numBytes);
byte[] ba = new byte[]{5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,9,0,0,0};
ta.WriteSomeBytes(ba);
//Read 5 Ints
ta.ReadBytesAsInts(5);
ta.Close();
}

public class TestAlloc
{
private int allocSize;
private readonly IntPtr allocPtr;
private int bytesToRead;

public TestAlloc(int size)
{
if ( size < 4 )
throw new ArgumentOutOfRangeException("Must alloc multiple of 4 bytes.");
if ( (size % 4) != 0 )
throw new ArgumentOutOfRangeException("Must alloc multiple of 4 bytes.");
allocSize = size;
allocPtr = Marshal.AllocHGlobal(size);
}

// Write some bytes to global memory.
public void WriteSomeBytes(byte[] ba)
{
if ( ba.Length > allocSize )
throw new ArgumentOutOfRangeException("Array too big.");
Marshal.Copy(ba, 0, allocPtr, ba.Length);
bytesToRead = ba.Length;
}

// Read int[] from global memory.
public int[] ReadAsIntArray(int count)
{
if ( count < 1 )
throw new ArgumentException("count must be greater then one.");
if ( (count * 4) > bytesToRead )
throw new ArgumentException("count greater then number of integers
available.");
int[] ia = new int[count];
Marshal.Copy(allocPtr, ia, 0, count);
return ia;
}
//Read global bytes as ints without a copy.
public unsafe void ReadBytesAsInts(int count)
{
if ( count < 1 )
throw new ArgumentException("count must be greater then one.");
if ( (count * 4) > bytesToRead )
throw new ArgumentException("count greater then number of integers
available.");
int * pInt = (int *)allocPtr.ToPointer();
for (int i = 0; i < count; i++)
{
Console.WriteLine("Int{0} is:{1}", i, *pInt++);
}
}
public void Close()
{
Marshal.FreeHGlobal(allocPtr);
}
}

--
William Stacey, MVP

Ray Z said:
Thanks, Eric
Could you tell me is there any way to conver a byte[] to int []? Or, in
another approach, if I alloc a block of memory use Win32 API, could I conver
it to a byte[] without memory copy. I am working on image processing, copy
memory again and again is unacceptable.

Eric Gunnerson said:
I think you will have trouble with that approach.

There is no way for you to persistantly fix/pin managed objects in C#. Fixed
objects have a big impact on the GC, and keeping them around would be bad.

If you really want to do this sort of thing, you should consider doing your
own memory allocation by calling into the Win32 memory apis yourself. You
should be able to take in arrays of whatever type you want, lock them, and
then copy stuff around as you wish.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
Ray Z said:
Thanks all.
I think I did not make my question clear.
I am going to write a MemoryPool which can manage a block memory to hold
image data. I'd like seperate the whole block into a few small pieces(double
buffer). I will put lock in every pieces. I can not use the Daniel's
solution because the memory block is pretty big. I want to use IntPtr
because I want to accept different type (byte, short and int)memory
referrence (or pointer). For examle, user already define a int []
Var1,
and
read image data (32 bits color format) from a file. he can attach Var1 to
the pool. and, when he want to process the Red color data in the data, he
can then get the byte[]Var2 (reference of same address of Var1) from the
pool.. In c#, looks we can not directly conver a int[] to a byte[].
And,
in
some case, the pool need accept void*.

Ray
 
Thanks, William
So far, I get the idea that if I want to use bothe unmanaged and managed
memory, I can not avoid memory copy. But I DO need to avoid it. I get a idea
that maybe I could use "union" to convert byte[] to int[] and so on. Here is
my source code, do you think this will work with GC?

[StructLayout(LayoutKind.Explicit)]

struct MyUnion

{

[FieldOffset(0)]

public int[] i;

[FieldOffset(0)]

public byte[] b;

}

After I define this "union". I can use the following code to alloc and
access the data buffer:
MyUnion mu = new MyUnion();
mu.a = new byte[640*480*4];
//if I like access it as int[]
int[] ip = mu.b;

will this work?



William Stacey said:
Here is a raw example with some ideas for you. If this does not help,
please explain in more detail what your after. Cheers!
--William Stacey, MVP

private void button34_Click(object sender, System.EventArgs e)
{
int numInts = 5;
int numBytes = numInts * 4;
TestAlloc ta = new TestAlloc(numBytes);
byte[] ba = new byte[]{5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,9,0,0,0};
ta.WriteSomeBytes(ba);
//Read 5 Ints
ta.ReadBytesAsInts(5);
ta.Close();
}

public class TestAlloc
{
private int allocSize;
private readonly IntPtr allocPtr;
private int bytesToRead;

public TestAlloc(int size)
{
if ( size < 4 )
throw new ArgumentOutOfRangeException("Must alloc multiple of 4 bytes.");
if ( (size % 4) != 0 )
throw new ArgumentOutOfRangeException("Must alloc multiple of 4 bytes.");
allocSize = size;
allocPtr = Marshal.AllocHGlobal(size);
}

// Write some bytes to global memory.
public void WriteSomeBytes(byte[] ba)
{
if ( ba.Length > allocSize )
throw new ArgumentOutOfRangeException("Array too big.");
Marshal.Copy(ba, 0, allocPtr, ba.Length);
bytesToRead = ba.Length;
}

// Read int[] from global memory.
public int[] ReadAsIntArray(int count)
{
if ( count < 1 )
throw new ArgumentException("count must be greater then one.");
if ( (count * 4) > bytesToRead )
throw new ArgumentException("count greater then number of integers
available.");
int[] ia = new int[count];
Marshal.Copy(allocPtr, ia, 0, count);
return ia;
}
//Read global bytes as ints without a copy.
public unsafe void ReadBytesAsInts(int count)
{
if ( count < 1 )
throw new ArgumentException("count must be greater then one.");
if ( (count * 4) > bytesToRead )
throw new ArgumentException("count greater then number of integers
available.");
int * pInt = (int *)allocPtr.ToPointer();
for (int i = 0; i < count; i++)
{
Console.WriteLine("Int{0} is:{1}", i, *pInt++);
}
}
public void Close()
{
Marshal.FreeHGlobal(allocPtr);
}
}

--
William Stacey, MVP

Ray Z said:
Thanks, Eric
Could you tell me is there any way to conver a byte[] to int []? Or, in
another approach, if I alloc a block of memory use Win32 API, could I conver
it to a byte[] without memory copy. I am working on image processing, copy
memory again and again is unacceptable.

Eric Gunnerson said:
I think you will have trouble with that approach.

There is no way for you to persistantly fix/pin managed objects in C#. Fixed
objects have a big impact on the GC, and keeping them around would be bad.

If you really want to do this sort of thing, you should consider doing your
own memory allocation by calling into the Win32 memory apis yourself. You
should be able to take in arrays of whatever type you want, lock them, and
then copy stuff around as you wish.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
Thanks all.
I think I did not make my question clear.
I am going to write a MemoryPool which can manage a block memory to hold
image data. I'd like seperate the whole block into a few small
pieces(double
buffer). I will put lock in every pieces. I can not use the Daniel's
solution because the memory block is pretty big. I want to use IntPtr
because I want to accept different type (byte, short and int)memory
referrence (or pointer). For examle, user already define a int [] Var1,
and
read image data (32 bits color format) from a file. he can attach
Var1
to
the pool. and, when he want to process the Red color data in the
data,
he
can then get the byte[]Var2 (reference of same address of Var1) from the
pool.. In c#, looks we can not directly conver a int[] to a byte[]. And,
in
some case, the pool need accept void*.

Ray
 
It depends on what you mean by "convert". If accessing it another way is
okay, that's fairly easy with unsafe code:

byte[] buffer = new byte[100];

fixed (byte*pBuffer = buffer)
{
int* pInt = (int*) pBuffer);

for (int i = 0; i < buffer.Length / 4; i++)
{
// do something with *pInt...
pInt++;
}
}

You can, if you know the size ahead of time, do something hacky with a
struct:

[StructLayout(LayoutKind.Explicit, Size=100)]
struct Test
{
[FieldOffset(0)]
int intValue;

[FieldOffset(0)]
byte byteValue;
}

Once you have that, you can get the address of the intValue or byteValue
fields, and then use pointer arithmetic to step through the rest of the
entries.



--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
Ray Z said:
Thanks, Eric
Could you tell me is there any way to conver a byte[] to int []? Or, in
another approach, if I alloc a block of memory use Win32 API, could I conver
it to a byte[] without memory copy. I am working on image processing, copy
memory again and again is unacceptable.

Eric Gunnerson said:
I think you will have trouble with that approach.

There is no way for you to persistantly fix/pin managed objects in C#. Fixed
objects have a big impact on the GC, and keeping them around would be bad.

If you really want to do this sort of thing, you should consider doing your
own memory allocation by calling into the Win32 memory apis yourself. You
should be able to take in arrays of whatever type you want, lock them, and
then copy stuff around as you wish.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
Ray Z said:
Thanks all.
I think I did not make my question clear.
I am going to write a MemoryPool which can manage a block memory to hold
image data. I'd like seperate the whole block into a few small pieces(double
buffer). I will put lock in every pieces. I can not use the Daniel's
solution because the memory block is pretty big. I want to use IntPtr
because I want to accept different type (byte, short and int)memory
referrence (or pointer). For examle, user already define a int []
Var1,
and
read image data (32 bits color format) from a file. he can attach Var1 to
the pool. and, when he want to process the Red color data in the data, he
can then get the byte[]Var2 (reference of same address of Var1) from the
pool.. In c#, looks we can not directly conver a int[] to a byte[].
And,
in
some case, the pool need accept void*.

Ray
 
Thanks, Eric
I get a idea just like you, but I can not know the size when I define the
structure. Here is
my source code, I wonder if this will work with GC?

[StructLayout(LayoutKind.Explicit)]

struct MyUnion

{

[FieldOffset(0)]

public int[] a;

[FieldOffset(0)]

public byte[] b;

}

After I define this "union". I can use the following code to alloc and
access the data buffer:
MyUnion mu = new MyUnion();
mu.a = new int[640*480];
//if I like access it as byte[]
byte[] bp = mu.b;

will this work?

Eric Gunnerson said:
It depends on what you mean by "convert". If accessing it another way is
okay, that's fairly easy with unsafe code:

byte[] buffer = new byte[100];

fixed (byte*pBuffer = buffer)
{
int* pInt = (int*) pBuffer);

for (int i = 0; i < buffer.Length / 4; i++)
{
// do something with *pInt...
pInt++;
}
}

You can, if you know the size ahead of time, do something hacky with a
struct:

[StructLayout(LayoutKind.Explicit, Size=100)]
struct Test
{
[FieldOffset(0)]
int intValue;

[FieldOffset(0)]
byte byteValue;
}

Once you have that, you can get the address of the intValue or byteValue
fields, and then use pointer arithmetic to step through the rest of the
entries.



--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
Ray Z said:
Thanks, Eric
Could you tell me is there any way to conver a byte[] to int []? Or, in
another approach, if I alloc a block of memory use Win32 API, could I conver
it to a byte[] without memory copy. I am working on image processing, copy
memory again and again is unacceptable.

Eric Gunnerson said:
I think you will have trouble with that approach.

There is no way for you to persistantly fix/pin managed objects in C#. Fixed
objects have a big impact on the GC, and keeping them around would be bad.

If you really want to do this sort of thing, you should consider doing your
own memory allocation by calling into the Win32 memory apis yourself. You
should be able to take in arrays of whatever type you want, lock them, and
then copy stuff around as you wish.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
Thanks all.
I think I did not make my question clear.
I am going to write a MemoryPool which can manage a block memory to hold
image data. I'd like seperate the whole block into a few small
pieces(double
buffer). I will put lock in every pieces. I can not use the Daniel's
solution because the memory block is pretty big. I want to use IntPtr
because I want to accept different type (byte, short and int)memory
referrence (or pointer). For examle, user already define a int [] Var1,
and
read image data (32 bits color format) from a file. he can attach
Var1
to
the pool. and, when he want to process the Red color data in the
data,
he
can then get the byte[]Var2 (reference of same address of Var1) from the
pool.. In c#, looks we can not directly conver a int[] to a byte[]. And,
in
some case, the pool need accept void*.

Ray
 
You can convert the int pointer to a byte pointer and use "[]" to index the
byte pointer if that helps.
However you can't cast a pointer to a managed type. So if you need a
managed byte[] and managed int[] pointing to same memory, I don't know a way
to do that. The union thing gets close, but that did not work fully after
testing (at least for me.) Will pointers not work for you? Why do you need
a byte[] and an int[]? Maybe there is a workaround if you explain your
needs a bit more. Cheers!

This works:
//use in unsafe context
int[] iArray = new int[]{5, 9};
int totBytesIArray = iArray.Length*4;
fixed( int * pi = iArray )
{
byte * pba = (byte*)pi;
for(int i =0; i < totBytesIArray; i++)
{
Console.Write("{0}: ", pba); //use [] to index the pointer.
}
Console.WriteLine();
}

--
William Stacey, MVP

Ray Z said:
Thanks, William
So far, I get the idea that if I want to use bothe unmanaged and managed
memory, I can not avoid memory copy. But I DO need to avoid it. I get a idea
that maybe I could use "union" to convert byte[] to int[] and so on. Here is
my source code, do you think this will work with GC?

[StructLayout(LayoutKind.Explicit)]

struct MyUnion

{

[FieldOffset(0)]

public int[] i;

[FieldOffset(0)]

public byte[] b;

}

After I define this "union". I can use the following code to alloc and
access the data buffer:
MyUnion mu = new MyUnion();
mu.a = new byte[640*480*4];
//if I like access it as int[]
int[] ip = mu.b;

will this work?



William Stacey said:
Here is a raw example with some ideas for you. If this does not help,
please explain in more detail what your after. Cheers!
--William Stacey, MVP

private void button34_Click(object sender, System.EventArgs e)
{
int numInts = 5;
int numBytes = numInts * 4;
TestAlloc ta = new TestAlloc(numBytes);
byte[] ba = new byte[]{5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,9,0,0,0};
ta.WriteSomeBytes(ba);
//Read 5 Ints
ta.ReadBytesAsInts(5);
ta.Close();
}

public class TestAlloc
{
private int allocSize;
private readonly IntPtr allocPtr;
private int bytesToRead;

public TestAlloc(int size)
{
if ( size < 4 )
throw new ArgumentOutOfRangeException("Must alloc multiple of 4 bytes.");
if ( (size % 4) != 0 )
throw new ArgumentOutOfRangeException("Must alloc multiple of 4 bytes.");
allocSize = size;
allocPtr = Marshal.AllocHGlobal(size);
}

// Write some bytes to global memory.
public void WriteSomeBytes(byte[] ba)
{
if ( ba.Length > allocSize )
throw new ArgumentOutOfRangeException("Array too big.");
Marshal.Copy(ba, 0, allocPtr, ba.Length);
bytesToRead = ba.Length;
}

// Read int[] from global memory.
public int[] ReadAsIntArray(int count)
{
if ( count < 1 )
throw new ArgumentException("count must be greater then one.");
if ( (count * 4) > bytesToRead )
throw new ArgumentException("count greater then number of integers
available.");
int[] ia = new int[count];
Marshal.Copy(allocPtr, ia, 0, count);
return ia;
}
//Read global bytes as ints without a copy.
public unsafe void ReadBytesAsInts(int count)
{
if ( count < 1 )
throw new ArgumentException("count must be greater then one.");
if ( (count * 4) > bytesToRead )
throw new ArgumentException("count greater then number of integers
available.");
int * pInt = (int *)allocPtr.ToPointer();
for (int i = 0; i < count; i++)
{
Console.WriteLine("Int{0} is:{1}", i, *pInt++);
}
}
public void Close()
{
Marshal.FreeHGlobal(allocPtr);
}
}

--
William Stacey, MVP

Ray Z said:
Thanks, Eric
Could you tell me is there any way to conver a byte[] to int []? Or, in
another approach, if I alloc a block of memory use Win32 API, could I conver
it to a byte[] without memory copy. I am working on image processing, copy
memory again and again is unacceptable.

I think you will have trouble with that approach.

There is no way for you to persistantly fix/pin managed objects in C#.
Fixed
objects have a big impact on the GC, and keeping them around would
be
bad.
If you really want to do this sort of thing, you should consider doing
your
own memory allocation by calling into the Win32 memory apis
yourself.
You
should be able to take in arrays of whatever type you want, lock
them,
and
then copy stuff around as you wish.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no
rights.
Thanks all.
I think I did not make my question clear.
I am going to write a MemoryPool which can manage a block memory
to
hold
image data. I'd like seperate the whole block into a few small
pieces(double
buffer). I will put lock in every pieces. I can not use the Daniel's
solution because the memory block is pretty big. I want to use IntPtr
because I want to accept different type (byte, short and int)memory
referrence (or pointer). For examle, user already define a int [] Var1,
and
read image data (32 bits color format) from a file. he can attach Var1
to
the pool. and, when he want to process the Red color data in the data,
he
can then get the byte[]Var2 (reference of same address of Var1)
from
the
pool.. In c#, looks we can not directly conver a int[] to a
byte[].
And,
in
some case, the pool need accept void*.

Ray
 
Hi Ray,

I found that you have posted a new post "covert between byte[] and int []"
for this issue.
I will follow up you there.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| From: "Ray Z" <[email protected]>
| References: <#[email protected]>
<#[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
| Subject: Re: Question about unsafe code
| Date: Mon, 3 Nov 2003 09:33:38 -0500
| Lines: 187
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.3790.0
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
| Message-ID: <[email protected]>
| Newsgroups: microsoft.public.dotnet.languages.csharp
| NNTP-Posting-Host: x42071bc2.ip.e-nt.net 66.7.27.194
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP12.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:196263
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Thanks, William
| So far, I get the idea that if I want to use bothe unmanaged and managed
| memory, I can not avoid memory copy. But I DO need to avoid it. I get a
idea
| that maybe I could use "union" to convert byte[] to int[] and so on. Here
is
| my source code, do you think this will work with GC?
|
| [StructLayout(LayoutKind.Explicit)]
|
| struct MyUnion
|
| {
|
| [FieldOffset(0)]
|
| public int[] i;
|
| [FieldOffset(0)]
|
| public byte[] b;
|
| }
|
| After I define this "union". I can use the following code to alloc and
| access the data buffer:
| MyUnion mu = new MyUnion();
| mu.a = new byte[640*480*4];
| //if I like access it as int[]
| int[] ip = mu.b;
|
| will this work?
|
|
|
| | > Here is a raw example with some ideas for you. If this does not help,
| > please explain in more detail what your after. Cheers!
| > --William Stacey, MVP
| >
| > private void button34_Click(object sender, System.EventArgs e)
| > {
| > int numInts = 5;
| > int numBytes = numInts * 4;
| > TestAlloc ta = new TestAlloc(numBytes);
| > byte[] ba = new byte[]{5,0,0,0,6,0,0,0,7,0,0,0,8,0,0,0,9,0,0,0};
| > ta.WriteSomeBytes(ba);
| > //Read 5 Ints
| > ta.ReadBytesAsInts(5);
| > ta.Close();
| > }
| >
| > public class TestAlloc
| > {
| > private int allocSize;
| > private readonly IntPtr allocPtr;
| > private int bytesToRead;
| >
| > public TestAlloc(int size)
| > {
| > if ( size < 4 )
| > throw new ArgumentOutOfRangeException("Must alloc multiple of 4
| bytes.");
| > if ( (size % 4) != 0 )
| > throw new ArgumentOutOfRangeException("Must alloc multiple of 4
| bytes.");
| > allocSize = size;
| > allocPtr = Marshal.AllocHGlobal(size);
| > }
| >
| > // Write some bytes to global memory.
| > public void WriteSomeBytes(byte[] ba)
| > {
| > if ( ba.Length > allocSize )
| > throw new ArgumentOutOfRangeException("Array too big.");
| > Marshal.Copy(ba, 0, allocPtr, ba.Length);
| > bytesToRead = ba.Length;
| > }
| >
| > // Read int[] from global memory.
| > public int[] ReadAsIntArray(int count)
| > {
| > if ( count < 1 )
| > throw new ArgumentException("count must be greater then one.");
| > if ( (count * 4) > bytesToRead )
| > throw new ArgumentException("count greater then number of integers
| > available.");
| > int[] ia = new int[count];
| > Marshal.Copy(allocPtr, ia, 0, count);
| > return ia;
| > }
| > //Read global bytes as ints without a copy.
| > public unsafe void ReadBytesAsInts(int count)
| > {
| > if ( count < 1 )
| > throw new ArgumentException("count must be greater then one.");
| > if ( (count * 4) > bytesToRead )
| > throw new ArgumentException("count greater then number of integers
| > available.");
| > int * pInt = (int *)allocPtr.ToPointer();
| > for (int i = 0; i < count; i++)
| > {
| > Console.WriteLine("Int{0} is:{1}", i, *pInt++);
| > }
| > }
| > public void Close()
| > {
| > Marshal.FreeHGlobal(allocPtr);
| > }
| > }
| >
| > --
| > William Stacey, MVP
| >
| > | > > Thanks, Eric
| > > Could you tell me is there any way to conver a byte[] to int []? Or,
in
| > > another approach, if I alloc a block of memory use Win32 API, could I
| > conver
| > > it to a byte[] without memory copy. I am working on image processing,
| copy
| > > memory again and again is unacceptable.
| > >
| > > | > > > I think you will have trouble with that approach.
| > > >
| > > > There is no way for you to persistantly fix/pin managed objects in
C#.
| > > Fixed
| > > > objects have a big impact on the GC, and keeping them around would
be
| > bad.
| > > >
| > > > If you really want to do this sort of thing, you should consider
doing
| > > your
| > > > own memory allocation by calling into the Win32 memory apis
yourself.
| > You
| > > > should be able to take in arrays of whatever type you want, lock
them,
| > and
| > > > then copy stuff around as you wish.
| > > >
| > > > --
| > > > Eric Gunnerson
| > > >
| > > > Visit the C# product team at http://www.csharp.net
| > > > Eric's blog is at http://blogs.gotdotnet.com/ericgu/
| > > >
| > > > This posting is provided "AS IS" with no warranties, and confers no
| > > rights.
| > > > | > > > > Thanks all.
| > > > > I think I did not make my question clear.
| > > > > I am going to write a MemoryPool which can manage a block memory
to
| > hold
| > > > > image data. I'd like seperate the whole block into a few small
| > > > pieces(double
| > > > > buffer). I will put lock in every pieces. I can not use the
Daniel's
| > > > > solution because the memory block is pretty big. I want to use
| IntPtr
| > > > > because I want to accept different type (byte, short and
int)memory
| > > > > referrence (or pointer). For examle, user already define a int []
| > Var1,
| > > > and
| > > > > read image data (32 bits color format) from a file. he can attach
| Var1
| > > to
| > > > > the pool. and, when he want to process the Red color data in the
| data,
| > > he
| > > > > can then get the byte[]Var2 (reference of same address of Var1)
from
| > the
| > > > > pool.. In c#, looks we can not directly conver a int[] to a
byte[].
| > And,
| > > > in
| > > > > some case, the pool need accept void*.
| > > > >
| > > > > Ray
| > > > >
| > > > >
| > > >
| > > >
| > >
| > >
| >
| >
|
|
|
 
Back
Top