Sign in to follow this  
Jonas B

[.net] Pointer to Array

Recommended Posts

Jonas B    100
I need to speed up some memory copying by using Buffer.BlockCopy(), but I can't find a way to cast my *byte to the required byte[]. Any tips?

Share this post


Link to post
Share on other sites
Jonas B    100
Buffer.BlockCopy() only accepts Arrays, and all I've got is a pointer. I thought Arrays and Pointers were similar enough to allow casting between them, but

byte* ptr = null;
byte[] array = (byte[])ptr;

doesn't compile.

Share this post


Link to post
Share on other sites
thannett    214
You can try something like this:

byte test = 'a'; //Example byte
byte* ptr = &test; //Pointer to Example byte
byte array[0]; //Array of bytes
array[0] = *ptr; //Makes array[0] equal to the contents of ptr
cout << array[0] << endl; //Prints contents of array[0]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Its been a while since i wrote C/C++ code but isnt an array always a pointer sort of? Just try what bakery2k1 adviced you to do.

Share this post


Link to post
Share on other sites
orbano    130
if you have a byte[] varname, the expression 'varname' is a pointer to the first element of the array (if its allocated), so its type is byte*.

Share this post


Link to post
Share on other sites
Jonas B    100
Sorry folks, I forgot to specify that the language is C#. The cast should work in C++ (and probably C++/CLI), so I (still) hope there's a way to do it in C# as well.
I'll try to remember that .NET != C# next time!

So, any clues for C#?

Share this post


Link to post
Share on other sites
Bob Janova    769
Can you use Marshal.Copy() instead? A pointer isn't equivalent to an array under .Net, because arrays know how long they are, so you won't be able to do a simple cast and I can't see a method on the Array class that would allow you to create one.

Share this post


Link to post
Share on other sites
Jonas B    100
Marshal.Copy() *almost* works - but this is from one unmanaged pointer to another, and all Marshal.Copy() methods involve Arrays in some form.

I can get by without it, it just annoys me to not have access to (possibly) optimized copy funtions...

Share this post


Link to post
Share on other sites
orbano    130
then simply iterate through your array given by the pointer (you must know its length), and put it into an array:

byte* bptr = your pointer thingie;
int l = length of the array pointed by your byte* ptr;
byte[] myArray = new byte[l];
for(int i=0; i<l; ++i)
{
myArray[i] = *bptr; //i dont know how to reference in c#
++bptr;
}

one more thing: if you cant tell the length of the array (l), then no God will tell you that :)

Share this post


Link to post
Share on other sites
orbano    130
you are moving data between a safe and an unsafe variable. thants the thing that .net doesnt really like and will not support with specific functions i think

Share this post


Link to post
Share on other sites
Jonas B    100
Sorry, my bad - your example was not like what I have. I have two unsafe pointers. Marshal.Copy() handles Pointer to Array copies, so that's allowed.

Share this post


Link to post
Share on other sites
Enselic    829
Are you sure you need to optimize that routine in the first place? Even though things look dirty, it doesn't mean it executes dirtly [smile].

And I'm curious of your more high level problem so to speak. What are you trying to do in a broad sense?

I am asking because I suspect you are a C/C++ guy just starting with C#, wanting to do things the C/C++ way when the prefered would be the C# way.

Share this post


Link to post
Share on other sites
Jonas B    100
Actually, C++ was a long time ago...
One of the uses is copying data from a sound buffer to a D3D surface (for effects processing on the GPU). At least in C++ I seem to remember that memcpy() can be significantly faster than the manual approach.

Share this post


Link to post
Share on other sites
capn_midnight    1707
Quote:
Original post by Enselic
Are you sure you need to optimize that routine in the first place? Even though things look dirty, it doesn't mean it executes dirtly [smile].

And I'm curious of your more high level problem so to speak. What are you trying to do in a broad sense?

I am asking because I suspect you are a C/C++ guy just starting with C#, wanting to do things the C/C++ way when the prefered would be the C# way.


I have to agree with Enselic. Just because there are pointers in C# doesn't mean you should use them.

Actually, C# implements object references similarly to Java. What is called an "object reference" is actually a pointer to that object, in C++ terminology. These would be equivalent blocks of code in both languages:

//C#
void doSomething(MyClass a)
{
a.modify(); //calling method of doSomething will see changes to a
a = new MyClass(); //wasted effort, the object reference is only a copy
}
//C++
void doSomething(MyClass* a)
{
a->modify(); //calling method of doSomething will see changes to a
a = new MyClass(); //wasted effort, the object pointer is only a copy
}

The significance is the parameter copying semantics. If the C# method were copied verbatim as a C++ function, then calling the function will create copies of the objects that are passed to the function. In C#, copies of the object references are made. When the C++ version in the code above is called, the object pointers are copied before being passed to the function. In both cases, the underlying object is NOT copied.

If we want equivalant C# code to C++ pass-by-reference, then we use the same ampersand syntax

//C++ and C#
void somethingElse(MyClass& a)
{
//blah!
}


There is no equivalent C# code for C++ pass-by-value for objects. Pass-by-value is used for stack-types (primitives, enums, structs), but never for heap-types.

The difference between pointers and references in C# is that the former is unmanaged and the latter is managed. The *only* time you need pointers in C# is when you are interoping with unmanaged C++ assemblies that require pointer parameters. There is a reason why you need a "unsafe" code block as well as a compiler flag to use pointers in C# -- you're not supposed to use them for general purpose work, they are only for very special purposes.

Share this post


Link to post
Share on other sites
Jonas B    100
I'm already a strong believer of the Way of the Managed Languages, but thanks anyway!
Pointers are very useful when processing certain types of data. Have you tried C# Image manipulation using Get/SetPixel()? Dog slow, the only decent way is to lock it and go unsafe with the pointer.

Share this post


Link to post
Share on other sites
orbano    130
Quote:
Original post by Jonas B
Actually, C++ was a long time ago...
One of the uses is copying data from a sound buffer to a D3D surface (for effects processing on the GPU). At least in C++ I seem to remember that memcpy() can be significantly faster than the manual approach.


A c# code runs on the CLR, its heap is not the same as the system heap used by a C++ programme. You dont have to (you cant) optimize copying blocks of data, like memcpy does. And even if you could... you dont really need to!

Image manipulation: copy the image to a 2D array :) then you dont need to access data via function calls.

Share this post


Link to post
Share on other sites
Jonas B    100
> Image manipulation: copy the image to a 2D array :) then you dont need to access data via function calls.

I'd be happy to use Arrays if that's what Locking returned. But it doesn't sound optimal to manually copy the data to an Array just in order to be able to use BlockCopy ;)

If you can prove that there's no way to optimize memory copy between two unmanaged areas, I'll believe it, but I must say it sounds a bit strange to me... I don't know much about the bare metal though.

Share this post


Link to post
Share on other sites
austcro    134
if you really want to do this under .NET without loops etc then provide a binding to the RtlMoveMemory/CopyMemory API function and do your copy with that. It's unsafe, but since your using pointers anyway I suspect that you don't really care.

Share this post


Link to post
Share on other sites
Jonas B    100
Thanks, I was hoping to avoid DllImport but maybe the P/Invoke overhead isn't so hefty. I hope to be able to run some tests and get back with hard facts before the topic's closed!

(For reference, here's how to use it)
[DllImport("Kernel32.dll", EntryPoint="RtlMoveMemory", SetLastError=false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, int size);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this