By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,786 Members | 1,143 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,786 IT Pros & Developers. It's quick & easy.

Pointers in .net

100+
P: 178
Hello everyone,


I have just started a project that requires a windows service that read output from a PCI card via an API. I've been unfortunate enough to be handed an ActiveX .ocx library that exposes methods to use, but with no documentation specific to using the methods available in a .NET environment (last API / driver update was Nov 02).


The method I need looks likes this - void MultiRead(short channel1, short channel2, ref float pDataBuffer).


As you can probably tell, the problem lies with the 3rd parameter, which is a pointer to a "one dimensional array." When I try to create a pointer to a byte[] I get this compilation error


"Cannot take the address of, get the size of, or declare a pointer to a managed type."



I know its a long shot , but has anyone had a problem like this before, and can you help me out? I need to know how I can create a one dimensional array capable of being populated with text or byte data, and which is also an object or struct that I can create a pointer to.
Apr 9 '09 #1
Share this Question
Share on Google+
6 Replies


Expert 100+
P: 427
Hi

It is possible to do this. You need to mark the function which calls to the API as Unsafe and use the pointers within a Fixed block.

Using the Unsafe keyword in your function declaration allows you to create pointers in C#.
The Fixed keyword tells the garbage collector to leave to pointers alone until code execution has exited the fixed block.

So basically all you need to do is create your function using the Unsafe keyword. Create a 'Fixed' block, write your code around pointers there and everything should work OK.
Apr 9 '09 #2

100+
P: 178
Hi,

Thanks for the reply. I am aware of what you have, but the problem is that I need to create a pointer to a 1 dimensional array which i'm struggling to do. I tried to point to a byte[] but I get a compliation error::



"Cannot take the address of, get the size of, or declare a pointer to a managed type."

I need to know how I can create a one dimensional array capable of being populated with text or byte data, and which is also an object or struct that I can create a pointer to. Any idea how to do this?
Apr 9 '09 #3

Expert 100+
P: 427
I'm not sure what problem you're having.
Could you maybe post the code which is giving you problems.

In your application properties under 'Build' did you allow unsafe code?

I wrote a little test which worked fine:

Expand|Select|Wrap|Line Numbers
  1.  private void Form1_Load(object sender, EventArgs e)
  2.         {
  3.             byte[] x = new byte[] {1,2,3,4,5};
  4.             test(x);
  5.         }
  6.  
  7.  private unsafe void test(byte[] src)
  8.         {
  9.             fixed (byte* pSrc = src)
  10.             {
  11.                 MessageBox.Show("First element: " +  pSrc[0].ToString() +  " Length of array: " + src.Length.ToString());
  12.             }
  13.         }
Apr 9 '09 #4

100+
P: 178
You have not assigned your pointer value using &src, which means you are not pointing to the memory address of the array, if I am not mistaken. You will not recieve a compilation error when not using &src, but I think this means your not actually pointing to the address in memory

The problem is the method signature is this::

Expand|Select|Wrap|Line Numbers
  1. void MultiRead(short channel1, short channel2, ref float pDataBuffer);
  2.  
Where pDataBuffer is a float pointer to the buffer (byte array). The documentation on this method doesn't help much, which is as follows:

Description :

Perform multiple channel AD conversions by software polling

Syntax

Sub Object.MultiRead(ByVal StartChannelNo as Integer,

ByVal EndChannelNo,ByRef ADbuffer as single)


Return : none


Argument :


StartChannelNo :Start Channel number of analog input (0~15)

EndChannelNo :Stop Channel number of analog input (0~15)

ADBuffer :Points to one-Dimension array with the size

of EndChannelNo-StartChannelNo+1


Any ideas ??
Apr 9 '09 #5

Expert 100+
P: 427
I changed the code as follows:

Expand|Select|Wrap|Line Numbers
  1.    private unsafe void test(byte[] src)
  2.         {
  3.             fixed (byte* pSrc = src)
  4.             {
  5.                 for (int i = 0; i < 5; i++)
  6.                 {
  7.                     pSrc[i] = 0;
  8.                     MessageBox.Show("Element number " + i.ToString() + " = " + src[i].ToString());
  9.                 }
  10.             }
  11.         }
This code shows that all the elements inside the src array now have a value of 0, so the pointer is pointing to the correct location as the data has changed.


I get the same results when changing the arguments to:

Expand|Select|Wrap|Line Numbers
  1. private unsafe void test(ref byte[] src)
I hope this helps you.. I'm running out of ideas :)
Apr 9 '09 #6

Plater
Expert 5K+
P: 7,872
You might want to use marshalling for this?

Not sure for sure how to use it, just pulled this from another post here on bytes, but play around with something like:
Expand|Select|Wrap|Line Numbers
  1. int len=4;//just guessing at this
  2. IntPtr data = Marshal.AllocHGlobal(len); 
  3. byte a;
  4. byte b;
  5.  
  6. try 
  7. {
  8.     MultiRead(a, a, data).
  9.  
  10.     byte[] returnBytes = new byte[len]; 
  11.     Marshal.Copy(data, returnBytes, 0, len); 
  12.  
  13.     Marshal.FreeHGlobal(data); 
  14. }
  15.  
Apr 9 '09 #7

Post your reply

Sign in to post your reply or Sign up for a free account.