0

I have some code:

private static st_createInstance        createInstance;
private static st_destroyInstance       destroyInstance;
private static st_getVersionId          getVersionId;
private static st_getVersionString2     getVersionString2;

//...

[UnmanagedFunctionPointer (CallingConvention.StdCall)]
private delegate IntPtr st_createInstance ();

[UnmanagedFunctionPointer (CallingConvention.StdCall)]
private delegate void st_destroyInstance (IntPtr pHandle);

//...

Now how to null all these delegates using reflections? (Idk how to compare Fields with delegate type).

EDIT: I want to null all of them in simple way, like foreach loop. Don't want to specify each field name.

apocalypse
  • 5,764
  • 9
  • 47
  • 95
  • (1) Nest them inside a `struct` (value class). You can have just one static instance. (2) Assign the static member variable with a new instance just created using `new`. – Ben Voigt Jul 24 '13 at 21:56

2 Answers2

2

If type is the type of object where the delegate fields are, try this:

var fields = type.GetFields(BindingFlags.Static | BindingFlags.NonPublic);

fields = fields.Where(f => f.FieldType.BaseType == typeof(System.MulticastDelegate));

foreach (FieldInfo fi in fields)
{
    fi.SetValue(null, null);
}

First null in SetValue means it's a static field, second one is for setting the value of the field to null.

RobSiklos
  • 8,348
  • 5
  • 47
  • 77
  • See my question, I explained it better now. – apocalypse Jul 24 '13 at 21:31
  • It cannot cast. So I modified line "fields = fields.Where ..." to "var newFields = fields.Where ...". It works ok now, but there is an additional fields which I dont understand: System.Func`2[[System.Reflection.FieldInfo, mscorlib, Version=4.0.0.0, Culture=n eutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=4.0. 0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] – apocalypse Jul 24 '13 at 21:53
  • I updated my new answer shortly after I posted it - make sure you have `f => f.FieldType.BaseType` instead of just `f => f.BaseType`. – RobSiklos Jul 25 '13 at 01:56
1

This strongly hints at an XY question. Always a problem when the OP doesn't explain why he needs to do something. You would write this kind of code when you are trying to do the job that the pinvoke marshaller does with the [DllImport] attribute.

If this is accurate at all then do note that there's very little point in setting these delegate objects back to null, even though they are static. They actually refer to a thunk, a tiny piece of auto-generated code that marshals between unmanaged and managed code. Usually it isn't anything more than a simple JMP instruction, it gets more convoluted when the stack frame needs to be rejiggered.

The delegate object itself requires a tiny spit of GC heap, only 32 bytes. You'll want to avoid writing code that uses reflection to get rid of ~36 bytes, there's just no payoff in either time or space. The code is already larger than the memory you release. Not to mention the true cost, you maintaining this code.

Consider getting rid of the code that initializes these delegates. There almost never is a need, the pinvoke marshaller is already very good at doing that by itself. You just need to help it figure out where to find the DLL, there are much better ways than using LoadLibrary(). Check this answer for example.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • The [documentation says otherwise](http://msdn.microsoft.com/en-us/library/43yky316.aspx) The thunks *do* get freed. "the unmanaged marshaling code is deleted when the delegate is collected." – Ben Voigt Jul 24 '13 at 21:58
  • Oh my god, looks so complicated. I will read it carefuly tommorow because Im too tired now. I just wanted to null these delegates when GetDelegateForFunctionPointer will fail on one or more calls (for example if I loaded not this DLL file what I wanted). – apocalypse Jul 24 '13 at 22:04
  • If you could not load the DLL then there's never any way that you could initialize the delegate object in the first place. Improve your error handling, **never** ignore the return value of LoadLibrary and GetProcAddress. – Hans Passant Jul 24 '13 at 22:11
  • Scenario: 1) load wrong dll file 2) try to create delegates using GetDelegateForFunctionPointer. 3) if some delegates are null, there is wrong dll library, so i can throw exception or something. A) is this ok to use reflections to check all these delegates are not null? B) if library was wrong, so I just need to keep that static fields as they are witohut making them null? – apocalypse Jul 24 '13 at 22:17
  • What do you *really* hope to happen when the wrong DLL gets loaded? Trying to set them back to null is just papering over the problem. A NullReferenceException is **not** easier to diagnose than a good Win32Exception you can throw when you discover that the chips are down. I already explained why there isn't any point in setting bad delegate object reference back to null. The only way you can recover is by setting them to *good* delegate objects for the proper DLL. You've got about 0.01% odds that make that happen. – Hans Passant Jul 24 '13 at 22:24