Pointers in .net

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • cleary1981
    New Member
    • Jun 2008
    • 178

    Pointers in .net

    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.
  • cloud255
    Recognized Expert Contributor
    • Jun 2008
    • 427

    #2
    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.

    Comment

    • cleary1981
      New Member
      • Jun 2008
      • 178

      #3
      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?

      Comment

      • cloud255
        Recognized Expert Contributor
        • Jun 2008
        • 427

        #4
        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:

        Code:
         private void Form1_Load(object sender, EventArgs e)
                {
                    byte[] x = new byte[] {1,2,3,4,5};
                    test(x);
                }
        
         private unsafe void test(byte[] src)
                {
                    fixed (byte* pSrc = src)
                    {
                        MessageBox.Show("First element: " +  pSrc[0].ToString() +  " Length of array: " + src.Length.ToString());
                    }
                }

        Comment

        • cleary1981
          New Member
          • Jun 2008
          • 178

          #5
          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::

          Code:
          void MultiRead(short channel1, short channel2, ref float pDataBuffer);
          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.MultiRea d(ByVal StartChannelNo as Integer,

          ByVal EndChannelNo,By Ref 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 ??

          Comment

          • cloud255
            Recognized Expert Contributor
            • Jun 2008
            • 427

            #6
            I changed the code as follows:

            Code:
               private unsafe void test(byte[] src)
                    {
                        fixed (byte* pSrc = src)
                        {
                            for (int i = 0; i < 5; i++)
                            {
                                pSrc[i] = 0;
                                MessageBox.Show("Element number " + i.ToString() + " = " + src[i].ToString());
                            }
                        }
                    }
            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:

            Code:
            private unsafe void test(ref byte[] src)
            I hope this helps you.. I'm running out of ideas :)

            Comment

            • Plater
              Recognized Expert Expert
              • Apr 2007
              • 7872

              #7
              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:
              [code=c#]
              int len=4;//just guessing at this
              IntPtr data = Marshal.AllocHG lobal(len);
              byte a;
              byte b;

              try
              {
              MultiRead(a, a, data).

              byte[] returnBytes = new byte[len];
              Marshal.Copy(da ta, returnBytes, 0, len);

              Marshal.FreeHGl obal(data);
              }
              [/code]

              Comment

              Working...