struct -> null

  • Thread starter Thread starter Juan Gabriel Del Cid
  • Start date Start date
J

Juan Gabriel Del Cid

Structs are value types (in C++ and in C#), so NULL would be incompatible
with any struct type. Now, if you want to pass NULL for a reference type,
for example if yourfunction was declared like:

open (struct struct1 *str, struct struct1 *str2) { ... }

you would do so with IntPtr.Zero (that is NULL).

Hope that helps,
-JG
 
Hello,

if I have a P/Invoke method: open(STRUCT1 str, STRUCT2 str2);

is there a way to pass <null> for a struct in C#?
How can I solve this?

thx
 
Create two DllImports for the same api. The second one will be overloaded
with something like "object flag" on the STRUCT2 parm. Now you can pass a
STRUCT2 or a null ref. Example:

[DllImport("kernel32.dll")]
public static extern uint GetFileSize(
IntPtr hFile, //[in] Handle to the file for size.
ref uint fileSizeHigh); //[out] Pointer to var where high-order word is
returned.

[DllImport("kernel32.dll")]
public static extern uint GetFileSize(
IntPtr hFile, //[in] Handle to the file for size.
object flag); //[out] Overloaded to allow passing null.
 
From the help on IntPtr.Zero: "The value of this field is not equivalent to
a null reference..."
Wouldn't you be passing a ptr to the IntPtr struct that contains a zero? Or
does pInvoke change this to a null ref?
 
is there a way to pass <null> for a struct in C#?
How can I solve this?

In addition to what the other suggested, another way is to use unsafe
code and a real pointer type

STRUCT1* str

And yet another option is to change the parameter type to an array

STRUCT1[] str

and then either pass in a single-element array or null.



Mattias
 
From the help on IntPtr.Zero: "The value of this field is not
equivalent to a null reference..."

Of course it's not a null reference, it's a value type. In the past there
was no distinction between a value type and a reference type. You could cast
data to whatever you wanted and back. For example, a pointer is really
nothing more than an integer (4 bytes on a 32 bit processor). In this case,
NULL is just 4 bytes all set to zero (just like IntPtr.Zero).

So, in C/C++ you have:

if ((int)NULL == 0) {
// this is always true
}

and in C# you have:

if ((int)null == 0) {
// this will never compile because you can't convert
// null (or any other reference type)
// to an int (or any other value type)
}

if ((int)IntPtr.Zero == 0) {
// this is always true
}

Hope that clears it up for you,
-JG
 
I'd bet that the method you're trying to call takes a pointer to a struct,
and you should be using:

open(ref STRUCT1 str, ref STRUCT2 str2);

--
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.
 
In terms of the OP question, IntPtr does not help him. Assume the exported
function is something like:
BOOL DoSomething(SOMESTRUCT * struct1);

And the managed struct and/or class is:
// Declares a managed structure for the unmanaged structure.
[ StructLayout( LayoutKind.Sequential )]
public struct MyStruct
{
public int one = 1;
public long two =2;
}
// Declares a managed class for the unmanaged structure.
[ StructLayout( LayoutKind.Sequential )]
public class MyClass
{
public int one = 1;
public long two = 2;
}

Then his exports might be something like (among others):
// Because MyStruct is a value type, you cannot pass null as a
// parameter. Instead, declare an overloaded method.
[ DllImport( "Kernel32.dll" )]
public static extern bool DoSomething(
ref MyStruct myStruct );

[ DllImport( "Kernel32.dll" )]
public static extern bool DoSomething(
int flag ); // Declares an int instead of a structure reference so you
can pass a zero.

// Because MyClass is a class, you can also pass null as parameter.
// No overloading is needed.
[ DllImport( "Kernel32.dll", EntryPoint="DoSomething" )]
public static extern bool DoSomething2(
MyClass myClass );

Then he can call "DoSomething" like:
MyStruct ms;
MyClass mc = new MyClass();
bool b = DoSomething(ref ms); //Call using ref to struct.
bool b = DoSomething(0); //Call passing zero. You could pass
(int)IntPtr.Zero here, but why?
bool b = DoSomething2(mc); //Call using ref to class.
bool b = DoSomething2(null); //Call passing null.

In none of those cases does IntPtr help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top