Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pin a function pointer

I need to pass a managed callback to an unmanaged TCP receiver. Since its a thread that needs to exist for the lifetime of the application, I need to prevent it from getting garbage collected. I have read everywhere that pinning function pointers is not required and the GCHandle.Alloc will do the job of preventing garbage collection.

But is this a given? I have seen that the AppPool hosting this code crashes with an access violation. Why should I not suspect the fact that this error occurs because the function pointer was garbage collected?

This post supports this fact.

Update: This seems to have reduced the crashes considerably. Is there a problem with this approach?

typedef void (__cdecl *ProcMessageFunc)(void* param, void* paramBuf, ULONG bufSize);
FuncDelegate^ fp = gcnew MessageFuncDelegate(this, &Handler); 
pin_ptr<MessageFuncDelegate^> pinnedFunctionPointer = &fp; 
ret = Receiver ((ProcMessageFunc)pinnedFunctionPointer);
like image 429
Krishter Avatar asked Jul 09 '12 17:07

Krishter


1 Answers

I do exactly what you suggest to do - GCHandle.Alloc on the delegate but with no pinning - and have not had any problems in extensive use on many different platforms and on .NET versions 2.0 - 4. Something like:

 DelegateHandle = GCHandle.Alloc(xlDelegate);
 FunctionPointer = Marshal.GetFunctionPointerForDelegate(xlDelegate);

with FunctionPointer then passed to the native code, and DelegateHandle kept for later cleanup.

This seems to be the best reference: http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.80).aspx.

Nothing in the post you point to contradicts this reference - you do need to protect the delegate from garbage collection, it's just that pinning is not required.

like image 117
Govert Avatar answered Nov 13 '22 08:11

Govert