Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Managed C++/CLI
  4. C++/CLI - Pin a function pointer

C++/CLI - Pin a function pointer

Scheduled Pinned Locked Moved Managed C++/CLI
questionc++hostinghelpcareer
2 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    krishter
    wrote on last edited by
    #1

    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? Why does pinning the pointer as below reduce the number of crashes?

    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);

    P 1 Reply Last reply
    0
    • K krishter

      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? Why does pinning the pointer as below reduce the number of crashes?

      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);

      P Offline
      P Offline
      Paul Michalik
      wrote on last edited by
      #2

      Difficult to say from what you have shown. You can pin a handle to a managed object only temporarily, since a pin_ptr can only be created on the stack. Therefore, if you have something like this:

      IntPtr YourClass::GetFuncPointer()
      {
      FuncDelegate^ fp = gcnew MessageFuncDelegate(this, &Handler);
      pin_ptr pinnedFunctionPointer = &fp;
      return ((ProcMessageFunc)pinnedFunctionPointer);
      }

      then you effectively have only pinned fp for the duration of this method call. A correct way to do this depends on your scenario. I'd recommend something along the lines of the following (I didn't compile it, but you get the idea):

      public ref class ClientRegistrar abstract sealed {
      static FuncDelegate^ s_ManagedReceiverList;

      // ...
      public static void RegisterClient(YourClient^ p\_Client)
      {
          // thread safety for free
          s\_ManagedReceiverList += 
              gcnew MessageFuncDelegate(p\_Client, &YourClient::Handler);
      
          // here I assume that ::Receiver is an unmanaged global function which
          // takes a funtion pointer of type ProcMessageFunc. Don't know
          // if you need to deal with multiple registrations....
          ::Receiever((ProcMessageFunc)Marshal::GetFunctionPointerForDelegate(s\_ManagedReceiver));
      }
      
      public static void UnregisterClient(YourClient^ p\_Client)
      {
          s\_ManagedReceiverList -=
              gcnew  MessageFuncDelegate(p\_Client, &YourClient::Handler);
          // use the same schema to unregister from the native receiver
      }
      

      }

      Usage (C#):

      YourClient tClient = new YourClient();
      // ...
      ClientRegistrar.RegisterClient(tClient);
      // ...

      s_ManagedReceiverList and any YourClient instance you register via RegisterClient will be kept alive as long as the current application domain will exist. Implement UnregisterClient if you need more fine grained control. A delegate does not need to be pinned, the CLR takes care of proper handling of that. It just needs to be kept alive. Cheers, Paul

      1 Reply Last reply
      0
      Reply
      • Reply as topic
      Log in to reply
      • Oldest to Newest
      • Newest to Oldest
      • Most Votes


      • Login

      • Don't have an account? Register

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • World
      • Users
      • Groups