none
Marshalling a NULL pointer RRS feed

  • Question

  • Hi,
       I would like to know how does the CLR marshal a C null pointer.

      Eg: C code :  int* ptr = NULL;  is marshalled into IntPtr.Zero , or does it fill an IntPtr variable with a random number?

      I need to know this since i am using P/Invoke to call a function from a dll which might return a pointer pointing to NULL.

    thx in advance
    Peter
    Thursday, April 16, 2009 2:01 PM

Answers

  • If it returns a NULL pointer, you'll get IntPtr.Zero on the managed side.
    Mattias, C# MVP
    • Marked as answer by Peter_MLT Thursday, April 16, 2009 2:26 PM
    Thursday, April 16, 2009 2:17 PM
    Moderator

All replies

  • If it returns a NULL pointer, you'll get IntPtr.Zero on the managed side.
    Mattias, C# MVP
    • Marked as answer by Peter_MLT Thursday, April 16, 2009 2:26 PM
    Thursday, April 16, 2009 2:17 PM
    Moderator
  • okay thx mate.
    Thursday, April 16, 2009 2:26 PM
  • BTW: Easy way how to get your answer quickly is it to try it on a small example ...
    Using IntPtr.Zero as NULL is also mentioned in article Calling Win32 DLLs in C# with P/Invoke as better way than casting 0 to IntPtr.
    Thursday, April 16, 2009 5:19 PM
    Moderator
  • Hi,
       I would like to know how does the CLR marshal a C null pointer.

      Eg: C code :  int* ptr = NULL;  is marshalled into IntPtr.Zero , or does it fill an IntPtr variable with a random number?

      I need to know this since i am using P/Invoke to call a function from a dll which might return a pointer pointing to NULL.

    thx in advance
    Peter
    How would that compare to a pointer to void in C?  i.e. LPVOID InBuffer

    Jer 29:11
    Tuesday, April 28, 2009 5:09 PM
  • An LPVOID in C/C++ is basically the same as IntPtr in C#.

    It is just an untyped pointer to an address in memory.  Since you're using a void*, you're saying you don't care what type of object is being referenced, only that it's a memory location.

    IntPtr is the same way - it's basically just a reference to a location, saved in a platform-appropriate sized place.


    Reed Copsey, Jr. - http://reedcopsey.com
    Tuesday, April 28, 2009 5:13 PM
    Moderator
  • Reed,

    Thanks for the reply.  If a function has a signature with a parameter of IntPtr, I want then to pass it a reference to an array or maybe an int.  Can I have one signature that satisfies both types of parameters?

    Al
    Jer 29:11
    Tuesday, April 28, 2009 11:20 PM
  • Well, you'd need to know what that IntPtr was trying to represent on the C/C++ side of things.

    If you pass it the wrong thing, it's likely to crash.  This is one of the nice things C# tries to avoid, and is always an issue when working with raw pointers (which LPVOID/IntPtr basically represent).

    However, I don't recommend using an IntPtr to marshall an int (at least not an Int32).  On 64 bit platforms, IntPtr is 64bits, so it's 2x the size of an int.
    Reed Copsey, Jr. - http://reedcopsey.com
    Tuesday, April 28, 2009 11:53 PM
    Moderator
  • So then what does that mean in terms of the function signature?  Does that mean I need one for each type that will be represented?  That's what was convenient with C++.  using void* meant you could use mostly anything.
    Jer 29:11
    Wednesday, April 29, 2009 1:20 AM
  • No - you can use the same type signature, and use IntPtr on the C# side of things.  The only difference is that, in order to get your random data into an IntPtr, you're going to have to either copy it, or use unsafe code to pin a pointer to the element, and cast it into the IntPtr.  This will work the same way as it does in C++, but requires unsafe context (since you're basically doing what is, by definition, considered "unsafe" in C#).
    Reed Copsey, Jr. - http://reedcopsey.com
    Wednesday, April 29, 2009 3:49 PM
    Moderator
  • No - you can use the same type signature, and use IntPtr on the C# side of things.  The only difference is that, in order to get your random data into an IntPtr, you're going to have to either copy it, or use unsafe code to pin a pointer to the element, and cast it into the IntPtr.  This will work the same way as it does in C++, but requires unsafe context (since you're basically doing what is, by definition, considered "unsafe" in C#).
    Reed Copsey, Jr. - http://reedcopsey.com
    Can you provide an example or link to one?

    Thanks Reed,

    Al

    Jer 29:11
    Thursday, April 30, 2009 11:58 AM
  • Let's see... some samples.

    To copy, you would want to use the Marshall class.  I'd post a sample, but this is pretty well covered in this CodeProject article:
    http://www.codeproject.com/KB/vb/Marshal.aspx


    For assigning random data into and out of an IntPtr, this will work:

    unsafe void Test()
    {
        float myRandomData = 5.0f;

        // Make an IntPtr out of the address of the float
        IntPtr pointerToData = new IntPtr(&myRandomData);

        // You can use pointToData at this point...
        float* floatPointerToData = (float*)pointerToData.ToPointer();
        *floatPointerToData = 10.0f;

        Console.WriteLine("myRandomData == {0}",myRandomData);
    }


    This prints:

    myRandomData == 10

    Basically, an IntPtr can point to anything - it's nothing but a memory address/location.  Since it can point to anything, you can use it for just about any purpose, especially if you're going to/from native code.  This is directly equivalent to a void* in C/C++ - an untyped pointer to some location of memory.

    Reed Copsey, Jr. - http://reedcopsey.com
    • Proposed as answer by alleyes Thursday, April 30, 2009 3:45 PM
    Thursday, April 30, 2009 3:25 PM
    Moderator
  • That's more than I expected.  Thanks much Reed!

    Jer 29:11
    Thursday, April 30, 2009 3:34 PM