Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IntPtr vs ref C#

Tags:

c#

i have to import unmanaged dll into my C# application, I want to know what is the diferent between IntPtr and ref, and what you recommnded me to use and why? Note that both ways are working to me. For example:

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Result Init(IntPtr versionInfo);

 [DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
 public static extern Result Init(ref Version versionInfo);
like image 928
Yellow Avatar asked Nov 14 '10 03:11

Yellow


People also ask

What is IntPtr in C?

The IntPtr type can be used by languages that support pointers and as a common means of referring to data between languages that do and do not support pointers. IntPtr objects can also be used to hold handles. For example, instances of IntPtr are used extensively in the System. IO.

What is IntPtr size?

The IntPtr type is designed to be an integer whose size is platform-specific. That is, an instance of this type is expected to be 32-bits on 32-bit hardware and operating systems, and 64-bits on 64-bit hardware and operating systems.


2 Answers

If Version is a struct that is compatible with the struct that the extern Init function expects, there is no significant difference between the two, except that the ref version will be a lot easier to use from C# since the runtime will manage all of the marshaling and pinning for you. Unless you really want to do all that work, I would stick with the ref option.

Of course, without seeing the C function prototype, the Version struct in C#, and the struct used in C for that parameter, I can really only guess.

like image 177
cdhowie Avatar answered Oct 25 '22 19:10

cdhowie


Edit: Based on some criticism forcing me to rethink this and research it further. I freely admit that IntPtr is error prone, I think there may be some debate on what "harder" means, but if the framework can marshall it automagically and keep you from having to pin things, etc if you do not use IntPtr then I think I am in agreement that IntPtr would be "harder. It appears to me after further research and thought that it would be easier (when you are forced to P/Invoke and can't make a C++/CLI wrapper) to declare your struct (in your case Version) in the managed code and then pass it via the ref parameter.

[StructLayout(LayoutKind.Sequential)]
struct Version
{
    // Data members
}

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern Result Init(ref Version versionInfo);

My guess would be you would want the IntPtr version. The difference is that IntPtr is a class that manages a pointer to memory, whereas declaring a parameter as a reference (ref keyword) in an argument list means that you are passing by reference. In general when passing data to and from an unmanaged dll via a P/Invoke call, unless the data being passed is a vanilla type (int, double, string - with appropriate Marshal decoration) I pass data as an IntPtr. You can then Marshal the IntPtr to your managed declaration of the unmanaged struct.

You should check out this link for more information on P/Invoke calls: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx

like image 3
pstrjds Avatar answered Oct 25 '22 19:10

pstrjds