Will passing of IntPtr as function's parameter cause memory leak? - c#

Let's say I have IntPtr variable, its value has been assigned via call of WinApi function (p/invoke). Then I passed that value in 10 different functions. Since IntPtr is struct (value type), each function will get a copy of the original variable. Will it cause memory leak? Should I close each copy of the original variable in each function?
[DllImport("WinApiFunction")]
public static extern bool WinApiFunction(int arg1, int arg2, out IntPrt result)
public void Foo()
{
var result = IntPtr.Zero;
WinApiFunction(1, 2, out result);
Foo1(result);
Foo2(result);
Foo3(result);
//...
Foo10(result);
// ...
CloseHandle(result);
}

IntPtr is often used as a place holder for handle or pointer values. It's hard to tell from the code exactly what is happening but copying a handle or pointer value wouldn't copy the underlying resource.
So in your example it seems correct to CloseHandle once. I would put it into a try..finally though to ensure that CloseHandle is always called if WinApiFunction returned a valid handle.
[DllImport("WinApiFunction")]
public static extern bool WinApiFunction(int arg1, int arg2, out IntPrt result)
public void Foo()
{
var result = IntPtr.Zero;
if (!WinApiFunction(1, 2, out result) || result == IntPtr.Zero)
{
throw new Exception("Oops");
}
try
{
Foo1(result);
Foo2(result);
}
finally
{
CloseHandle(result);
}
}
If you would build a proxy class around the handle this the use case to implement a finalizer (and IDisposable) on the proxy class.

Related

Is it safe to pass a struct with "ref this" to native code

I am currently integrating the Steamworks SDK into my game and have a couple of methods which require to pass a struct as a pointer, for example:
// Public interface method declared by the library
S_API bool SteamAPI_SteamNetworkingIPAddr_IsLocalHost( SteamNetworkingIPAddr* self );
// C# implementation
[StructLayout(LayoutKind.Explicit, Size = 18, Pack = 1)]
public struct SteamNetworkingIPAddr {
// My current usage of "ref this"
public bool IsLocalhost => NativeMethods.SteamAPI_SteamNetworkingIPAddr_IsLocalHost(ref this);
// How another library solves it
public bool IsLocalhost {
get {
SteamNetworkingIPAddr copy = this;
NativeMethods.SteamAPI_SteamNetworkingIPAddr_IsLocalHost(ref self);
}
}
private static class NativeMethods {
[DllImport(SteamAPI.LIBRARY_NAME, EntryPoint = "SteamAPI_SteamNetworkingIPAddr_IsLocalHost", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool SteamAPI_SteamNetworkingIPAddr_IsLocalHost(ref SteamNetworkingIPAddr self);
}
}
I am a bit concerned about passing this with ref to the native method because I've seen other implementations which create a copy of the struct before passing it but I could not find something which officially says that it's either safe or unsafe to do so.
So, my question is - should I make a copy or keep my solution?
In a instance method or property of a struct, the implicit this parameter is a ref managed reference. So any changes to the struct do mutate (change) the struct passed in.
Therefore, when you call the native function, you are passing an actual reference to your own struct. So it is possible for your caller to see these changes, if they have passed in a reference to their own struct. But depending on how your caller makes this call, there may be a defensive copy anyway.
For example:
var isLocal = SomeClass.IPAddrProperty.IsLocalhost
this will create a copy of the struct, and any changes will disappear.
Whereas this:
var ipAddr = SomeClass.IPAddrProperty;
var isLocal = ipAddr.IsLocalhost;
SomeClass.IPAddrProperty = ipAddr;
means that the results are copied back.

How to correctly call P/Invoke methods in a class library?

I have multiple projects in a Visual Studio 2015 solution. Several of these projects do P/Invokes like:
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
public static extern int GetIpNetTable(IntPtr pIpNetTable, [MarshalAs(UnmanagedType.U4)]
ref int pdwSize, bool bOrder);
So I moved all my P/Invokes to a separate class library and defined the single class as:
namespace NativeMethods
{
[
SuppressUnmanagedCodeSecurityAttribute(),
ComVisible(false)
]
public static class SafeNativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int GetTickCount();
// Declare the GetIpNetTable function.
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
public static extern int GetIpNetTable(IntPtr pIpNetTable, [MarshalAs(UnmanagedType.U4)]
ref int pdwSize, bool bOrder);
}
}
From the other projects, this code is called as:
int result = SafeNativeMethods.GetIpNetTable(IntPtr.Zero, ref bytesNeeded, false);
All compiles without error or warning.
Now running FxCop on the code gives the warning:
Warning CA1401 Change the accessibility of P/Invoke
'SafeNativeMethods.GetIpNetTable(IntPtr, ref int, bool)' so that it is
no longer visible from outside its assembly.
Ok. Changing the accessibility to internal as:
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
internal static extern int GetIpNetTable(IntPtr pIpNetTable, [MarshalAs(UnmanagedType.U4)]
ref int pdwSize, bool bOrder);
Now causes the hard error of:
Error CS0122 'SafeNativeMethods.GetIpNetTable(IntPtr, ref int, bool)'
is inaccessible due to its protection level
So how can I make this work without error or warning?
Thanks in advance for any help as I've been going in circles for hours!
It is a sure thing that you will agree with statement that PInvoke methods are not the most pleasant things to call from C# code.
They are:
Not so strongly typed - often riddled with IntPtr and Byte[] parameters.
Error prone - it is easy to pass some incorrectly initialized parameter, like a buffer with wrong length, or some struct with field not initialized to that struct's size...
Obviously don't throw exceptions if something goes wrong - it is their consumer's responsibility to check the return code or Marshal.GetLastError() it. And more often then not, someone forgets to do it, leading to hard-to-track bugs.
In comparison with these issues FxCop warning is but a meager style checker peeve.
So, what can you do? Deal with those three issues and FxCop will go by itself.
These are the things I recommend you to do:
Do not expose any API directly. It is important for complex functions, but applying it for any function will actually deal with your primary FxCop issue:
public static class ErrorHandling
{
// It is private so no FxCop should trouble you
[DllImport(DllNames.Kernel32)]
private static extern void SetLastErrorNative(UInt32 dwErrCode);
public static void SetLastError(Int32 errorCode)
{
SetLastErrorNative(unchecked((UInt32)errorCode));
}
}
Don't use IntPtr if you can use some safe handle.
Don't just return Boolean or (U)Int32 from wrapper methods - check for return type inside the wrapper method and throw the exception if required. If you want to use a method in exception-less manner, then provide Try-like version that will clearly denote that it is a no-exception method.
public static class Window
{
public class WindowHandle : SafeHandle ...
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport(DllNames.User32, EntryPoint="SetForegroundWindow")]
private static extern Boolean TrySetForegroundWindowNative(WindowHandle hWnd);
// It is clear for everyone, that the return value should be checked.
public static Boolean TrySetForegroundWindow(WindowHandle hWnd)
{
if (hWnd == null)
throw new ArgumentNullException(paramName: nameof(hWnd));
return TrySetForegroundWindowNative(hWnd);
}
public static void SetForegroundWindow(WindowHandle hWnd)
{
if (hWnd == null)
throw new ArgumentNullException(paramName: nameof(hWnd));
var isSet = TrySetForegroundWindow(hWnd);
if (!isSet)
throw new InvalidOperationException(
String.Format(
"Failed to set foreground window {0}",
hWnd.DangerousGetHandle());
}
}
Don't use IntPtr or Byte[] if you can use normal structs passed by ref/out. You may say that it is obvious, but in many cases where a strongly typed struct can be passed I have seen IntPtr being used instead. Don't use out parameters in your public-facing methods. In most cases it is unnecessary - you can just return the value.
public static class SystemInformation
{
public struct SYSTEM_INFO { ... };
[DllImport(DllNames.Kernel32, EntryPoint="GetSystemInfo")]
private static extern GetSystemInfoNative(out SYSTEM_INFO lpSystemInfo);
public static SYSTEM_INFO GetSystemInfo()
{
SYSTEM_INFO info;
GetSystemInfoNative(out info);
return info;
}
}
Enums. WinApi uses a lot of enum values as parameters or return values. Being a C style enum they are actually passed(returned) as simple integers. But C# enums are actually nothing more than integers too, so assuming that you have set proper underlying type, you will have much easier to use methods.
Bit/Byte twiddling - whenever you see that getting some values or checking their correctness requires some masks, then you can be sure that it can be better handled with custom wrappers. Sometimes it is handled with FieldOffset, sometimes a bit of actual bit twiddling should be done, but in any case it will be done only in one place, providing simple and handy object model:
public static class KeyBoardInput
{
public enum VmKeyScanState : byte
{
SHIFT = 1,
CTRL = 2, ...
}
public enum VirtualKeyCode : byte
{
...
}
[StructLayout(LayoutKind.Explicit)]
public struct VmKeyScanResult
{
[FieldOffset(0)]
private VirtualKeyCode _virtualKey;
[FieldOffset(1)]
private VmKeyScanState _scanState;
public VirtualKeyCode VirtualKey
{
get {return this._virtualKey}
}
public VmKeyScanState ScanState
{
get {return this._scanState;}
}
public Boolean IsFailure
{
get
{
return
(this._scanState == 0xFF) &&
(this._virtualKey == 0xFF)
}
}
}
[DllImport(DllNames.User32, CharSet=CharSet.Unicode, EntryPoint="VmKeyScan")]
private static extern VmKeyScanResult VmKeyScanNative(Char ch);
public static VmKeyScanResult TryVmKeyScan(Char ch)
{
return VmKeyScanNative(ch);
}
public static VmKeyScanResult VmKeyScan(Char ch)
{
var result = VmKeyScanNative(ch);
if (result.IsFailure)
throw new InvalidOperationException(
String.Format(
"Failed to VmKeyScan the '{0}' char",
ch));
return result;
}
}
P.S.: And do not forget about correct function signatures (bitness and other issues), marshaling of types, layout attributes and char set (also, not forgetting to use DllImport(... SetLastError = true) is of utmost importance). http://www.pinvoke.net/ may often help, but it doesn't always provide the best signature to use.
P.S.1: And I recommend you to organize your NativeMethods not into one class , because it will quickly become one huge unmanageable pile of quite different methods, but instead to group them into separate classes (I actually use one partial root class and nested classes for each functional area - a bit more of tedious typing, but much better context and Intellisense). For class names I just use the same classification MSDN uses to group API functions. Like for GetSystemInfo it is "System Information Functions"
So, if you apply all those advises, you will be able to create a robust, easy to use native wrapper library that hides all the unnecessary complexities and error-prone constructs, but that will look very familiar to anyone who knows the original API.

How to convert the returned interface variable by a method to object?

I am using a c# wrapper, in the c++ library, the called function returns a pointer to the class object.
In the c# wrapper, if I call that method it returns an interface variable.
That interface variable is null, so I am unable gets the values.
How should I handle that interface variable in order to get values.
Anyone please help me.
In the below code we have ROOTNET.Interface.NTH1F it is an interface, where ROOTNET.NTH1F is a class
using ROOTNET.Utility;
using ROOTNET.Interface;
NTH1F g = new ROOTNET.NTH1F("g", "background removal", doubleArrayX.Length - 1,
doubleArrayX);
g.SetContent(doubleArrayY);
g.GetXaxis().SetRange(xmin, xmax);
ROOTNET.NTH1F bkg = new ROOTNET.NTH1F(g);
bkg.Reset();
bkg.Add(g.ShowBackground(80, ""));
In the above Im expecting the backgroung removed values to be saved in bkg but bkg contains all zeros, can you please help me in getting background removed values of g into bkg.
Where as the code of ShowBackground(int niter, string option) method is
public unsafe virtual NTH1 ShowBackground (int niter, string option)
{
NetStringToConstCPP netStringToConstCPP = null;
NetStringToConstCPP netStringToConstCPP2 = new NetStringToConstCPP (option);
NTH1 bestObject;
try
{
netStringToConstCPP = netStringToConstCPP2;
int num = *(int*)this._instance + 912;
bestObject = ROOTObjectServices.GetBestObject<NTH1> (calli ((), this._instance, niter, netStringToConstCPP.op_Implicit (), *num));
}
catch
{
((IDisposable)netStringToConstCPP).Dispose ();
throw;
}
((IDisposable)netStringToConstCPP).Dispose ();
return bestObject;
}
You cannot treat a pointer value returned from C++ as an interface (unless it's a COM interface, I guess). C++ and C# classes and interfaces may (and mostly probably do) have different low-level structures, so you cannot simply cast one onto another.
The only way is to write another wrapper around C++ class returned by your library. It should look more less like that:
C++/DLL:
__declspec(dllexport) void * ReturnInstance()
{
return new MyClass();
}
__declspec(dllexport) void MyClass_CallMethod(MyClass * instance)
{
instance->Method();
}
C#:
[DllImport("MyDll.dll")]
private static extern IntPtr ReturnInstance();
class MyClassWrapper
{
private IntPtr instance;
[DllImport("MyDll.dll")]
private static extern void MyClass_CallMethod(IntPtr instance);
public MyClassWrapper(IntPtr newInstance)
{
instance = newInstance;
}
public void Method()
{
MyClass_CallMethod(instance);
}
}
// (...)
IntPtr myClassInstance = ReturnInstance();
MyClassWrapper wrapper = new MyClassWrapper(myClassInstance);
wrapper.Method();
Hope this helps.

How do I call a function in a C++ Dll from C# that has void* callback and object parameter

I am trying to create a wrapper to a C dll and I am trying to call a function that has takes a callback function, receives an object as a pointer that is passed back.
The .h file delares
extern int SetErrorHandler(void (*handler) (int, const char*, void*),
void *data_ptr);
The handler is a callback function that is called when an error occurs and the data_ptr is any object (state) that is passed back to you, in the case of my app that will just be this (current object).
I am able to call functions in a dll that uses marshalled constant types like simple types strings, ints etc. But I cant figure out how to just marshall a pointer to a C# object that is the state.
In order to pass the object reference to the C function from what I have find by searching here and otherwise it seems that I need a structure type to be able to marshall to the function so I created a struct to hold my object:
[StructLayout(LayoutKind.Sequential)]
struct MyObjectState
{
public object state;
}
EDIT: I tried to put an attribute: [MarshalAs(UnmanagedType.Struct, SizeConst = 4)] on the public object state property, but this produces the same error, so I removed it, doesnt seem it would work anyway.
The struct contains a single object property to hold any object for the callback function.
I declared the delegate in C# as follows:
delegate void ErrorHandler(int errorCode, IntPtr name, IntPtr data);
Then I declared the import function in C# as follows:
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int SetErrorHandler handler, IntPtr data);
Then I created a callback function in my C# code:
void MyErrorHandler(int errorCode, IntPtr name, IntPtr data)
{
var strName = Marshal.PtrToStringAnsi(name);
var state = new MyObjectState();
Marshal.PtrToStructure(data, state);
Console.WriteLine(strName);
}
I am able to call the library function as follows:
var state = new MyObjectState()
{
state = this
};
IntPtr pStruct = Marshal.AllocHGlobal(Marshal.SizeOf(state));
Marshal.StructureToPtr(state, pStruct, true);
int ret = SetErrorHandler(MyErrorHandler, pStruct);
The call works and the callback function is called but I am unable to access the data in the callback function and when i try Marshal.PtrToStructure I get an error:
The structure must not be a value class.
I did a lot of searching here and found various things on Marshall and void* but nothing has helped me to get this to work
Thanks.
You are making this more complicated than it needs to be. Your C# client does not need to use the data_ptr parameter because a C# delegate already has a built in mechanism for maintaining the this pointer.
So you can simply pass IntPtr.Zero to the delegate. Inside your error handler delegate you just ignore the value of data_ptr since this will be available.
In case you don't follow this description, here's a short program to illustrate what I mean. Note how MyErrorHandler is an instance method that acts as the error handler, and can modify instance data.
class Wrapper
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void ErrorHandler(int errorCode, string name, IntPtr data);
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int SetErrorHandler(ErrorHandler handler, IntPtr data);
void MyErrorHandler(int errorCode, string name, IntPtr data)
{
lastError = errorCode;
lastErrorName = name;
}
public Wrapper()
{
SetErrorHandler(MyErrorHandler, IntPtr.Zero);
}
public int lastError { get; set; }
public string lastErrorName { get; set; }
}
class Program
{
static void Main(string[] args)
{
Wrapper wrapper = new Wrapper();
}
}
There may very well be a way to do this, but I gave up a long time ago. The solution I've come up with is slightly hackish, but it's very effective and works with everything I've thrown at it:
C# -> Managed C++ -> Native calls
Doing it this way you end up writing a small wrapper in managed C++, which is kind of a pain, but I found to be more capable and less painful than all of that marshaling code.
Honestly though I'm kind of hoping that someone gives a non-evasive answer, I've struggled with this for quite a while myself.

C# Interop: Out params that can also be null

Consider the following DllImport:
[DllImport("lulz.so")]
public static extern int DoSomething(IntPtr SomeParam);
This is actually referencing a C style function like this:
int DoSomething(void* SomeParam);
Consider that SomeParam is an "out" param, but can also be NULL. The C function behaves differently if the param is NULL. So I would probably want:
[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);
But, if I make it an out param in my import, I cannot pass it NULL, i.e. I can't do this:
int retVal = DoSomething(IntPtr.Zero)
What are my options here?
If you're trying to pass a value, then out is not the right keyword; change it to ref. You'll still need to explicitly pass a variable, but it can be a null reference.
For example...
[DllImport("lulz.so")]
public static extern int DoSomething(ref IntPtr SomeParam);
You can then call it like this:
IntPtr retVal = IntPtr.Zero;
DoSomething(ref retVal);
However
What is telling you that it needs to be either out or ref? Passing an IntPtr as out or ref is really akin to passing a double pointer. It would actually seem more appropriate to pass the parameter as an IntPtr.
The typical procedure is either to allocate the necessary memory in managed code and pass an IntPtr representing that allocated memory, or IntPtr.Zero to represent a null pointer. You do not need to pass the IntPtr as out or ref in order to send data back to .NET; you only need to do that if the function you're calling would actually change the pointer's address.
I don't understand what the problem is....
This runs:
private void button2_Click(object sender, EventArgs e) {
object bar;
Method(out bar);
bar = IntPtr.Zero;
Method(out bar);
}
private void Method(out object foo) {
foo = null;
}
What's the intention of passing NULL? Is it intended to call the method as usual, but to simply not set the output parameter?
In that case, I think I'd just wrap the extern method with an overload in C#. That overload (without the out parameter) would be like this:
public void DoSomething()
{
IntPtr dummy;
DoSomething(out dummy);
}
I ran into this once. I ended up marshaling the pointer myself (see Marshal Members for the library functions to do so).
Personally, I'd import this function twice, first time with 'out' parameter, second with 'in'.
[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);
// call as DoSomethingWithNull(IntPtr.Zero)
[DllImport("lulz.so", EntryPoint="DoSomething")]
public static extern int DoSomethingWithNull(IntPtr SomeParam);
This will solve your problem and will make code more readable.

Categories