none
GCHandle.Alloc pin non-bittable object? (ServiceHost) RRS feed

  • Question

  • Hello

    I need some analog of GCHandle.Alloc for non-bittable type (in my example its ServiceHost that hosts Wcf services)
    ServiceHost^ host = gcnew ServiceHost(CalculatorService::typeid);
    GCHandle handle = GCHandle::Alloc(host, GCHandleType::Pinned);
    
    If i use GCHandle.Alloc i get  ArgumentException:  Object contains non-primitive or non-blittable data error.

    The main idea is to get a handle to my object and pass it to an unmanaged program (this is the only way i need). Something like
    return (HANDLE)GCHandle::ToIntPtr(handle).ToPointer();
    Need to say that then unmanaged code passes this handle to managed and it retrieves ServiceHost instance back. Is that possible?

    Thank you
    Thursday, January 21, 2010 12:13 AM

Answers

  • I figured out how to achieve my goal after reading J. Richter's book "Clr via c#". In fact my GCHandleType doesnt need to be pinned, and because GCHandle objects are not movvable, i just set GCHandleType to Normal and now it works for me
    • Marked as answer by GarF1eld Thursday, January 21, 2010 2:51 PM
    Thursday, January 21, 2010 2:50 PM

All replies

  • Most likely, there is a much better way to deal with this.

    When your ServiceHost is created, how about adding it to a List or Hashtable.  Then you could use the List index (assuming you do not remove from the List) or the Hashtable key (works better if removes are involved) as a stand-in for the pointer.

    (The above assumes that you know when to add and remove (if necessary) from the proposed data structure. There is a good chance that this is the case for ServiceHost.  If garbage collection of ServiceHost is a requirement, you might need to consider storing WeakReferences to ServiceHost in the data structure instead of ordinary strong references so that the garbage collection of the ServiceHost is not prevented due to the presence of this data structure.)

    Thursday, January 21, 2010 12:37 AM
  • Thank you, but it doesnt siutable for me. Let me describe the situation

    1) There is a win32 program (MyProgram.exe), that has its own script languange (like vba in ms excel). There is an ability to call functions from win32 dlls.
    2) On the other hand, there is developed and tested wcf service in managed assembly (MyService.dll)

    So i want to run my service from the program. For that purpose i've created win32 dll with clr support. Here's some code

    // ---------------------------------------------------------------
    // creates service and returnes handle on GCHandle
    // ---------------------------------------------------------------
    _DLLAPI HANDLE __stdcall CreateExportService(const wchar_t* serverName)
    {
    		ExportService^ service = gcnew ExportService(gcnew String(serverName));
    		service->Open();
    
    		GCHandle handle = GCHandle::Alloc(service, GCHandleType::Pinned); // exception
    		return (HANDLE)GCHandle::ToIntPtr(handle).ToPointer();
    }
    
    // ---------------------------------------------------------------
    // closes service
    // ---------------------------------------------------------------
    _DLLAPI void __stdcall DestroyExportService(const HANDLE hService)
    {
    	GCHandle handle = GCHandle::FromIntPtr(IntPtr(hService));
    
    	ExportService^ service = (ExportService^)handle.Target;
    	service->Close();
    }
    
    As there is application domain that unloads with exiting from the program all i need to do is to prevent moving and garbage collection on my service.
    Thursday, January 21, 2010 12:53 AM
  • I figured out how to achieve my goal after reading J. Richter's book "Clr via c#". In fact my GCHandleType doesnt need to be pinned, and because GCHandle objects are not movvable, i just set GCHandleType to Normal and now it works for me
    • Marked as answer by GarF1eld Thursday, January 21, 2010 2:51 PM
    Thursday, January 21, 2010 2:50 PM