Click here to Skip to main content
12,699,220 members (25,040 online)
Click here to Skip to main content
Add your own
alternative version


29 bookmarked

Convert a Delegate to a Function pointer to Implement Callback function

, 2 Feb 2003
Rate this:
Please Sign up or sign in to vote.
Convert a delegate to a function pointer to implement callback function, for mixed Managed C++ and unmanaged C++ coding, and for DLL call.


These days, I've read the article Implementing Callback functions using IJW (avoiding DllImport), by Nishant S. From which I benefited much. And I wonder if there is some way to convert a delegate to a function pointer, I've got it at last.

When you are calling a function which is in a DLL, and that function requires a callback function pointer. First you can use DllImport (if you like to do so), which is a simple solution. But I don’t like DllImport. What's more, some times the function I want to call is not in a DLL. That is if I am coding mixed Managed C++ and Unmanaged C++. Even DllImport will not work. There are several ways to call a Managed C++ function in unmanaged C++ code.

  1. Use static function
     //managed class
    __gc class classA1 {
        public: static void func1(int nArg)    {
    //unmanaged class
    class classB1 {
        public: classB1(int nArg)    {
            m_nCount = nArg;
        public: void func1()  {
        protected: int m_nCount;

    When I need a non-static function to be called, there is the second solution.

  2. Use a managed object as a parameter.
     //managed class
    __gc class classA1 {
        public : void func2(int nArg)  {
    //unmanaged class
    class classB1 {
        public: classB1(int nArg) {
            m_nCount = nArg;
        public : void func2(classA1* pClassA1)     {
        protected: int m_nCount;

    It seems to work well, but when the one which call pClassA1->func2(…) is not the function classB1:: func2(…)]. Maybe classB1:: func2(…) calls other object’s member function, and the function calls others, at last pClassA1->func2(…) is called sadly. You must hold pClassA1 as a parameter to run for a long way, blessing there is no virtual function. Virtual functions can’t have managed object as parameter. And an unmanaged object can’t have a member variable to hold managed object.

  3. Make a function pointer which points to an instance member function.

    I have not found any method in .NET framework SDK to convert a delegate to a function pointer straightly yet, but I noticed Marshal::StructToPtr() which announced to be able to convert a managed struct to unmanaged memory block. What it does is to wrap the delegate in the managed struct, then convert the struct to an unmanaged block. At the beginning I used an unmanaged struct that has a field of a function pointer act as the unmanaged memory block, like this:

    typedef void (*PFUNC)(int)
    Struct PFUNC_Wrapper
        PFUNC thepfunc;

    Use the managed struct like this:

    __delegate void MyDelegate(int nArg);
    [StructLayoutAttribute( LayoutKind::Sequential, 
                           CharSet = CharSet::Ansi )]
    __gc struct Delegate_Wrapper
        MyDelegate*  _theDelegate;

    Then I convert the managed struct to an unmanaged struct. At the field of PFUNC thepfunc I got the function pointer. Ooh I got it! But soon I found I could also convert the unmanaged struct to a function pointer instead of accessing the member field of PFUNC thepfunc. Like this: *(PFUNC*)(&theUnmanagedStruct). Here you must have seen that the unmanaged struct is useless. So I just use a PFUNC to receive the data as an unmanaged memory block.

The source code

 __gc class classA1 {    
    public : void func2(int nArg) {
typedef void (*PFUNC)(int);

class classB1 {
    public: classB1(int nArg) {
        m_nCount = nArg;
    public: virtual void func3(PFUNC pCallback){
        if(pCallback != NULL)    {
    protected: int m_nCount;
__delegate void MyDelegate(int nArg);

[StructLayoutAttribute( LayoutKind::Sequential, CharSet = CharSet::Ansi )]
__gc struct Delegate_Wrapper
    MyDelegate*  _theDelegate;

// This is the entry point for this application
int _tmain(void)
    // TODO: Please replace the sample code below with your own.
    Console::WriteLine(S"Hello World");

    //create instance of managed classA1
    classA1* theA1 = new classA1();

    //create instance of Delegate_Wrapper
    Delegate_Wrapper* theWrapper = new Delegate_Wrapper();
    theWrapper->_theDelegate = new MyDelegate(theA1,&classA1::func2);
    //Convert the Delegate to Function Pointer.
    PFUNC pFnc;
    //create instance of unmaged classB1
    classB1 theB1(3);

    //use the function pointer as a callback function
    return 0;

Ensure that the garbage collector does not reclaim the delegate before the callback function completes its work.


A managed class’s member function can be used through a function pointer. Even if it is a non-static function!!


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

Web Developer
United States United States
A programer
Born in China
work in Japan
25 years old

You may also be interested in...


Comments and Discussions

QuestionMarshal directive exception was unhandled Pin
A.Gokulakannan25-Aug-09 18:42
memberA.Gokulakannan25-Aug-09 18:42 
QuestionMarshal.GetFunctionPointerForDelegate? Pin
blue2v10-Apr-09 10:29
memberblue2v10-Apr-09 10:29 
AnswerRe: Marshal.GetFunctionPointerForDelegate? Pin
Zhixiang Zhu15-May-12 23:16
memberZhixiang Zhu15-May-12 23:16 
General!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Don´t use this code !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Pin
Elmue22-Apr-08 17:52
memberElmue22-Apr-08 17:52 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Don´t use this code !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Your code works at the first look.
But if you put it into a bigger project you will notice that it fails very ugly.

Your example code only works because you execute the Callback IMMEDIATELY after calling Marshal::StructureToPtr().
But if you let pass some time between calling StructureToPtr() and executing the callback, the application is aborted without any usefull error messasge - a SILENT CRASH.

The reason is that the framework moves objects around in memory and a delegate's address in memory is only valid for a while and then it becomes invalid.

The very strange thing is the way Visual Studio (2003) behaves:
The callbacks functioned in my project when starting the application directly from Visual Studio with the key F5.
But if I started the same application hitting CTRL + F5 it failed!!


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Don´t use this code !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

There are ONLY few reliable ways to call callbacks from unmanaged C++ code :

Call a STATIC managed function directly from unmanaged C++ code without using any delegate.

Create a GCHandle from the delegate and pass the GCHandle to unmanaged code instead of a function pointer.

If you want something that behaves like a real callback, it becomes more complicated:
Inside your managed class (__gc), which you want to be called back from unmanaged code you have to put an inner unmanaged (__nogc) class.

If you want to see a working code which uses a callback from unmanaged C++ code into a managed class, download the latest version of my CabLib.dll.
There study the file LibExtract.h and you see how to do it the correct way!

You find the latest version of CabLib here

You need CabLib version 9.0 from April 2008, in older versions you will not find these callbacks!


I gave your artivle the worst note because you did a poor testing and I spent an entire weekend finding out the reason and a solution. It seems that you did not understand what Nish wrote in his article.

I asked Codeproject to delete your article as it misleads programmers around the world to waste their time with this code which simply does not work!

Questionhello world ! Pin
bibiboule2-Jan-07 22:33
memberbibiboule2-Jan-07 22:33 
QuestionWhat about an ArrayList instead an Int???? Pin
franjie27-May-05 4:45
memberfranjie27-May-05 4:45 
Generalmanaged class as member variable in unmanaged class Pin
baiju.km17-Aug-04 4:30
memberbaiju.km17-Aug-04 4:30 
GeneralSuccessive invocations fail Pin
hnipak16-Sep-03 4:14
susshnipak16-Sep-03 4:14 
GeneralRe: Successive invocations fail Pin
nutty11-Jul-04 21:55
membernutty11-Jul-04 21:55 
GeneralRe: Declaring Managed class as Member variable in an unmanaged class Pin
baiju.km24-Aug-04 2:52
memberbaiju.km24-Aug-04 2:52 
GeneralRe: Successive invocations fail Pin
the-unforgiven13-Sep-05 4:18
memberthe-unforgiven13-Sep-05 4:18 
GeneralJust something to note Pin
leppie2-Apr-03 15:46
memberleppie2-Apr-03 15:46 
GeneralMore than one deleagte Pin
RonnyPutz12-Feb-03 5:48
memberRonnyPutz12-Feb-03 5:48 
QuestionHow about a VC++ 6.0 sample? Pin
WREY5-Feb-03 2:45
memberWREY5-Feb-03 2:45 
AnswerRe: How about a VC++ 6.0 sample? Pin
kero5-Feb-03 15:06
memberkero5-Feb-03 15:06 
GeneralRe: How about a VC++ 6.0 sample? Pin
WREY4-Mar-03 4:20
memberWREY4-Mar-03 4:20 
GeneralRe: How about a VC++ 6.0 sample? Pin
Christian Graus7-Sep-06 1:40
staffChristian Graus7-Sep-06 1:40 
GeneralRe: How about a VC++ 6.0 sample? Pin
WREY7-Sep-06 5:47
memberWREY7-Sep-06 5:47 
GeneralRe: How about a VC++ 6.0 sample? Pin
Christian Graus9-Sep-06 16:28
staffChristian Graus9-Sep-06 16:28 
GeneralUnable to download source files. Pin
WREY4-Feb-03 7:06
memberWREY4-Feb-03 7:06 
GeneralRe: Unable to download source files. Pin
Jeremy Davis5-Feb-03 0:01
memberJeremy Davis5-Feb-03 0:01 
GeneralRe: Unable to download source files. Pin
WREY5-Feb-03 2:18
memberWREY5-Feb-03 2:18 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170118.1 | Last Updated 3 Feb 2003
Article Copyright 2003 by kero
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid