5,545,925 members and growing! (17,027 online)
Email Password   helpLost your password?
Languages » C# » COM Interop     Intermediate

Using managed delegate types in the unmanaged world

By NidhiGupta

An article on how to use managed delegate types in the unmanaged world.
C++, C#.NET 2.0, WinXP, Windows, .NETVisual Studio, VS2005, Dev

Posted: 8 Mar 2006
Updated: 8 Mar 2006
Views: 15,378
Bookmarked: 7 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
15 votes for this Article.
Popularity: 4.85 Rating: 4.13 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 6.7%
3
1 vote, 6.7%
4
13 votes, 86.7%
5

Introduction

Creating a delegate in .NET is extremely simple. However, in a rare case, you might have to create an object of the .NET delegate type with an unmanaged function pointer (in unmanaged world). This article explains a simple way to do the same.

Background

The problem I faced was:

In an ATL COM environment, I had to create an object of the .NET delegate type, AsyncCallback. In .NET, to create an object of this kind and assign a method to it is simple, by using a parameterized constructor. But in unmanaged COM world, parameterized constructors are not available, and it would be very difficult to do the same.

I solved this problem by creating a helper class in .NET which wraps an unmanaged function pointer (sent from the unmanaged world) as an AsyncCallback delegate. This delegate is then returned to the unmanaged world.

Using the code

Step 1. In .NET, create an interface IDelegateHelper. This interface provides a method AsyncCallbackDelegateWrapper that takes in a function pointer to an unmanaged function whose delegate is to be created. DelegateHelperCLass implements this interface. The method definition involves using Marshal.GeDelegateForFunctionPointer available in .NET to create a delegate out of the function pointer. The interface is provided for ease of use in the COM unmanaged world.

//Interface exposed to COM world 

[ComVisible(true), 
    GuidAttribute("2E9B141F-F876-4141-BCA3-F8B58DA0FE4F")]
public interface IDelegateHelper
{
    AsyncCallback 
      AsynCallbackDelegateWrapper(IntPtr funcPtr_in);
}

//Class exposed to COM world

[ComVisible(true)]
public class DelegateHelperCLass : IDelegateHelper
{
    public AsyncCallback 
      AsynCallbackDelegateWrapper(IntPtr funcPtr_in)
    {
        Delegate aAsyncCallbackDelegate = 
           Marshal.GetDelegateForFunctionPointer(funcPtr_in, 
           typeof(AsyncCallback));

        return aAsyncCallbackDelegate as AsyncCallback;
    }
}

Step 2. Export this .NET DLL into a TLB for use in COM. Use the tlbexp.exe utility to do the same. Register the .NET DLL using regasm.

tlbexp.exe DelegateHelper.dll 
           /out:F:\DelegateHelper.tlb

regasm.exe DelegateHelper.dll

Step 3. To use this in the unmanaged world (COM C++, here), create an instance of IDelegateHelper using CoCreateInstance. Then call the method AsynCallbackDelegateWrapper, passing the function pointer of the method whose delegate is to be created. The result obtained is a .NET delegate type.

//Import the TLBs

#import "C:\WINDOWS\Microsoft.NET\Framework" 
        "\v2.0.50215\mscorlib.tlb" 
        raw_interfaces_only, 
        raw_native_types, no_namespace, 
        named_guids, rename("_Module", "ReflectionModule"), 
        rename("ReportEvent", "ReportEventModule")
#import "F:\DelegateHelper.tlb" 
        raw_interfaces_only named_guids, no_namespace

//Add this to the library block in IDL 

//file for recognizing IAsyncResult* 

importlib("C:\WINDOWS\Microsoft.NET\" 
          "Framework\v2.0.50215\mscorlib.tlb");

//Create a function pointer FuncPtr that has 
//a signature same as that of the delgate methods
typedef void(*FuncPtr)(IAsyncResult*);

//CClient code that calls the helper methods
STDMETHODIMP CClient::CreateAsyncCallbackDelegate(void)
{
    //First create an instance of DelegateHelper class
    CComPtr<IDelegateHelper> aHelper;
    HRESULT hr = 
      aHelper.CoCreateInstance(CLSID_DelegateHelperCLass);
    if(FAILED(hr))
    {
        return E_FAIL;
    }
    
    //AsyncCallback delegate instnace 
    //that is to be populated with 
    _AsyncCallback* aCallBack = NULL;
    FuncPtr aPtr = TestMethod;
    hr = aHelper->AsynCallbackDelegateWrapper((long)aPtr, 
                                             &aCallBack);
    if(FAILED(hr))
    {
        return E_FAIL;
    }

    //*************************************
    //Now aCallBack can be used like 
    //a regular AsyncCallback instance!!
    //*************************************
    return S_OK;
}

//Some static method whose delegate is to be created
void CClient::TestMethod(IAsyncResult* asyncResult_in)
{
    //Your Callback code
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

NidhiGupta



Occupation: Web Developer
Location: India India

Other popular C# articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 5 of 5 (Total in Forum: 5) (Refresh)FirstPrevNext
Subject  Author Date 
QuestionAPi Problemmembert4urean3:36 13 Aug '06  
GeneralAlternatively...memberRichard Deeming8:44 15 Mar '06  
AnswerRe: Alternatively...membernidhig8321:16 15 Mar '06  
GeneralRe: Alternatively...memberRichard Deeming0:53 16 Mar '06  
GeneralCommentsmembermanish@siemens19:32 8 Mar '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 8 Mar 2006
Editor: Smitha Vijayan
Copyright 2006 by NidhiGupta
Everything else Copyright © CodeProject, 1999-2008
Web11 | Advertise on the Code Project