Click here to Skip to main content
14,972,994 members
Articles / Programming Languages / Perl
Posted 1 Feb 2008

Tagged as


30 bookmarked

Callback Functions and .NET C# COM Components

Rate me:
Please Sign up or sign in to vote.
4.36/5 (7 votes)
1 Feb 2008CPOL3 min read
How to make your C# component callback a Perl subroutine


Recently, my co-author had a requirement where he needed to convert a C# class library into a COM compatible component which could be called from either a C++/C#/Perl/Scripting environment. There was already a lot of information on how to implement this, but he had a somewhat more involved requirement. The requirement was that his Perl script needed to call a C# function (say Analyze()). The Analyze() function would typically take a long time to process, and the client needed to be updated regularly with the progress counter. This would be best solved using Callbacks.

However, there was scanty information available in a ready-to-use form, which could explain how to achieve this.

The article below explains how to handle multiple .NET events in a Perl environment.


This article is an attempt to explain the concept of Event Sources and Event Sinks as applicable to a COM client.

The code contains a C# COM Server, and a sample Perl Client which explains in the simplest manner possible, the concept of tapping the power of callback functions.

This article does the above by showing how to use the Win32::OLE module present in Perl, and using it to trap events generated in the .NET component.

Using the Code

To use the code attached, there are a few steps that need to be performed.

  1. Unzip the
  2. Browse to the CSharp_and_Scripting_New\CallBack Server\CallBack folder.
  3. Run register.bat
    1. In case the register.bat script does not work for you, open the project CallBack.sln in Visual Studio 2005. Go to the Tools Menu -> Visual Studio 2005 Command Prompt.
    2. Change directory in the command window to the CSharp_and_Scripting_New\CallBack Server\CallBack\bin\debug folder.
    3. Type regasm CallBack.dll /tlb:Callback.tlb
    4. type gacutil -i CallBack.dll
  4. Now that the .NET C# COM server is registered in your system, you can run the CSharp_and_Scripting_New\CallBack Client\ to view the output as shown below:



COM Server Code

The COM server has been written in C#. C# does not have any direct concept of function pointers. Instead, it defines something called delegates which is a safe form of a reference to a function. Now to tap the power of delegates, let us define some delegates as shown below in our class DotNetEventSender:

// No need to show this delegate to COM
public delegate void MyEventTarget(string msg);
public delegate void MyEventTarget2(int nTimerCounter);

public event MyEventTarget TheEvent;
public event MyEventTarget2 TheEvent2;  

As you can see above, we've declared two delegates of different types and associated two events with these delegates. Now let us declare an interface which our class will expose:

//This interface defines purely the events.
//DotNetEventSender should implement this interface with the
//ComSourceInterfaces() attribute to become an Event Source.

public interface CallBackEventInterface
    [DispId(1)] void TheEvent(string msg); 
    [DispId(2)] void TheEvent2(int nTimerCounter);

Our class will then expose this interface as shown below:

//Identifies these interfaces that are exposed as COM event sources 
//for the attributed class.

//Tells the compiler not to generate an interface automatically and that we are 
//implementing our own interface (IDotNetEventSender)
public class DotNetEventSender:IDotNetEventSender
{ ... 

Notice the attribute tag:


This tells the compiler that we are interested in exposing an event source for our class. The event sink will be then implemented in the Perl Client in a package which is expressly consuming (handling) all events generated by our C# server.

Now, it's not much use exposing an Event source, if we don't also implement some server functions that could be called by the Perl client. For example, the Perl client would call the function Run() which will start the timer in the C# server. This timer would then intermittently fire the event sources, which could then be handled in the Perl client.

So, let's now implement some class functions in the C# server.

private int m_nLoopCounter=0;
public void Run()
        Console.Out.WriteLine("Inside Run");
        //Note that the event handlers will be specified in the client
        //(e.g. Perl Script)     
        //start a timer which call the Events every one second.
        System.Timers.Timer progress = new System.Timers.Timer(1000);
        progress.Elapsed += new ElapsedEventHandler(TimerFunction);           

private void TimerFunction(object source, ElapsedEventArgs e)
        TheEvent("Hello, World!");

Perl Client Code

In the Perl client code, the basic step is to create an object of the C# server as shown below:

my $TM = Win32::OLE->new('CallBack.DotNetEventSender');

Once this is done, we want to inform the C# server that we are interested in receiving notifications when events of interest are generated on the server. We do this by stating:

Win32::OLE->WithEvents($TM, 'MyEvents');

Here, we are informing the C# server that all events should be forwarded to the package MyEvents. This package will define subroutines with names that are exactly the same as the events in the C# server.

package MyEvents;

#The name of the subroutine should be the exactly the same as the name of the
#event in the C# component.

sub TheEvent 
        my ($obj,$args) = @_;
        print "TheEvent() : ".$args."\n";

sub TheEvent2 
    my ($obj,$args) = @_;
    print "TheEvent2(): Timer Fired Count: ".$args."\n";

Now, it's not much use defining all the above code if we don't run a loop, which will keep the Perl client waiting for event messages to arrive. To do this, we add the code to the very end of the main package as shown below:

#keeps the Perl client active, processing the event messages as they
#occur repeatedly. 


That's it, folks! Just run the to see the above logic in action. Happy 'Interop'ing! :-)


  • 1st February, 2008: Initial post


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Authors

Bharat Mallapur
Technical Lead
India India
No Biography provided

Software Developer (Junior) Mediatek Inc
India India
No Biography provided

Comments and Discussions

GeneralWindows 7 [modified] Pin
Saamry22-Sep-10 10:11
MemberSaamry22-Sep-10 10:11 
GeneralRe: Windows 7 Pin
Bharat Mallapur24-Sep-10 22:12
MemberBharat Mallapur24-Sep-10 22:12 
GeneralRe: Windows 7 Pin
Saamry28-Sep-10 11:22
MemberSaamry28-Sep-10 11:22 
GeneralRe: Windows 7 Pin
Bharat Mallapur29-Sep-10 1:33
MemberBharat Mallapur29-Sep-10 1:33 
QuestionHow to make COM visible to others Pin
prashant_14430-Jul-09 2:07
Memberprashant_14430-Jul-09 2:07 
AnswerRe: How to make COM visible to others Pin
Bharat Mallapur30-Jul-09 20:21
MemberBharat Mallapur30-Jul-09 20:21 
GeneralRe: How to make COM visible to others Pin
prashant_14430-Jul-09 21:01
Memberprashant_14430-Jul-09 21:01 
GeneralRe: How to make COM visible to others Pin
Bharat Mallapur3-Aug-09 1:51
MemberBharat Mallapur3-Aug-09 1:51 
GeneralIn C++ Pin
jarekf1-Jul-09 8:12
Memberjarekf1-Jul-09 8:12 
GeneralRe: In C++ Pin
Bharat Mallapur1-Jul-09 23:08
MemberBharat Mallapur1-Jul-09 23:08 
GeneralRe: In C++ Pin
jarekf2-Jul-09 6:30
Memberjarekf2-Jul-09 6:30 
GeneralRe: In C++ Pin
Bharat Mallapur7-Jul-09 1:00
MemberBharat Mallapur7-Jul-09 1:00 
GeneralIn Javascript Pin
Navneet Hegde18-Mar-09 6:27
MemberNavneet Hegde18-Mar-09 6:27 
GeneralRe: In Javascript Pin
Bharat Mallapur18-Mar-09 19:34
MemberBharat Mallapur18-Mar-09 19:34 
GeneralRe: In Javascript Pin
Navneet Hegde18-Mar-09 20:51
MemberNavneet Hegde18-Mar-09 20:51 
GeneralMFC client Pin
manchukuo24-Nov-08 6:07
Membermanchukuo24-Nov-08 6:07 
GeneralRe: MFC client Pin
Bharat Mallapur1-Jul-09 23:13
MemberBharat Mallapur1-Jul-09 23:13 
GeneralHelp with C# client Pin
alon198026-Mar-08 10:42
Memberalon198026-Mar-08 10:42 
GeneralRe: Help with C# client Pin
Bharat Mallapur1-Apr-08 2:37
MemberBharat Mallapur1-Apr-08 2:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.