Callback function from native C to C++\CLI using non-static member or delegates

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • smmk25@hotmail.com

    Callback function from native C to C++\CLI using non-static member or delegates

    Before I state the problem, I just want to let the readers know, I am
    knew to C++\CLI and interop so please forgive any newbie questions.

    I have a huge C library which I want to be able to use in a .NET
    application and thus am looking into writing a managed C++ wrapper for
    in vs2005. Furthermore, this library has many callback hooks which
    need to be implemented by the C++ wrapper.

    These callback functions are declared as "extern C __cdecl" which I
    am still trying to understand why. However, that is not the main
    concern. My main question is , is there any possible way to implement
    the callback function to point to a non-static member function rather
    than a static function ?

    The reason being is that I need to be able to work with multiple
    instances of this wrapper, and if the callback functions are limited
    to static only, then obviously I would not be able to do this.

    I have seen some examples on the web, but those mainly deal with
    Windows API's, and don't seem to address this sort of issue.

    I would be interested to know if this is possible using delegates, or
    whether it is even possible to have the C callback function call a non-
    static member function of my C++ wrapper.

    Thanks in advance for our help

  • SvenC

    #2
    Re: Callback function from native C to C++\CLI using non-static member or delegates

    smmk25@hotmail. com wrote:
    I have a huge C library which I want to be able to use in a .NET
    application and thus am looking into writing a managed C++ wrapper for
    in vs2005. Furthermore, this library has many callback hooks which
    need to be implemented by the C++ wrapper.
    >
    These callback functions are declared as "extern C __cdecl" which I
    am still trying to understand why.
    Well, you have to choose a calling convention. extern C controls the name
    mangling which mangles less than C++ exports.
    concern. My main question is , is there any possible way to implement
    the callback function to point to a non-static member function rather
    than a static function ?
    No, because that defines how the function call is coded when it comes to
    machine code. A pointer to a class member function typically needs more
    information (the this pointer of the instance e.g.) and more code for being
    executed, so you cannot hand this information to a function pointer of the
    above type.
    The reason being is that I need to be able to work with multiple
    instances of this wrapper, and if the callback functions are limited
    to static only, then obviously I would not be able to do this.
    The only way I see would be that those callbacks would pass you a unique
    value which you can control when you initialize a callback. Some sort of
    cookie which lets you identify who initiated the callback when you are
    called back. But that of course would only work if that library was designed
    in that way.
    I have seen some examples on the web, but those mainly deal with
    Windows API's, and don't seem to address this sort of issue.
    Sometimes the windows Api uses an LPVOID param which can be seen as such a
    cookie. Was it that what you saw?
    I would be interested to know if this is possible using delegates, or
    Don't think so.
    whether it is even possible to have the C callback function call a
    non- static member function of my C++ wrapper.
    Don't think so either.

    --
    SvenC

    Comment

    • Carl Daniel [VC++ MVP]

      #3
      Re: Callback function from native C to C++\CLI using non-static member or delegates

      smmk25@hotmail. com wrote:
      Before I state the problem, I just want to let the readers know, I am
      knew to C++\CLI and interop so please forgive any newbie questions.
      >
      I have a huge C library which I want to be able to use in a .NET
      application and thus am looking into writing a managed C++ wrapper for
      in vs2005. Furthermore, this library has many callback hooks which
      need to be implemented by the C++ wrapper.
      >
      These callback functions are declared as "extern C __cdecl" which I
      am still trying to understand why. However, that is not the main
      concern. My main question is , is there any possible way to implement
      the callback function to point to a non-static member function rather
      than a static function ?
      >
      The reason being is that I need to be able to work with multiple
      instances of this wrapper, and if the callback functions are limited
      to static only, then obviously I would not be able to do this.
      >
      I have seen some examples on the web, but those mainly deal with
      Windows API's, and don't seem to address this sort of issue.
      >
      I would be interested to know if this is possible using delegates, or
      whether it is even possible to have the C callback function call a
      non- static member function of my C++ wrapper.
      There are basically two approaches to getting into a member function of some
      class instance from a simple function pointer callback.

      1. The API that uses the callback includes a "context" parameter of
      sufficient size to hold a pointer. For example, you might have declarations
      something like this:

      void RegisterCallbac k(int (*cbfn)(int p1,int p2,void* context), void*
      context);

      Here, a hypothetical callback registration function accepts a pointer to a
      function and an additional void* argument. When the callback is called, the
      context argument of the register function is passed to the context parameter
      of the callback function. Many Windows APIs that use callbacks use this
      pattern.

      In a case like this, you can write a small "trampoline function" that makes
      the jump from a simple function to a member function:

      class SomeClass(
      {
      // ...
      int Callback(int p1, int p2) { ... }
      };

      int CallbackTrampol ine(int p1, int p2, void* context)
      {
      return static_cast<Som eClass*>(contex t)->Callback(p1,p2 );
      }

      2. The API doesn't provide a context object (or "cookie").

      In this case, the API was simply not designed to support object-oriented
      usage, so your only recourse for getting the callback to call into a member
      function involves dynamic code generation. Basically, you have to write
      code that generates the above trampoline function at runtime, burning the
      address of the object into the function. Such code is subtle and
      non-portable, but the technique is used more than one might guess.

      -cd


      Comment

      • Ben Voigt

        #4
        Re: Callback function from native C to C++\CLI using non-static member or delegates


        "Carl Daniel [VC++ MVP]" <cpdaniel_remov e_this_and_nosp am@mvps.org.nos pam>
        wrote in message news:euqYSYgnHH A.588@TK2MSFTNG P06.phx.gbl...
        smmk25@hotmail. com wrote:
        >Before I state the problem, I just want to let the readers know, I am
        >knew to C++\CLI and interop so please forgive any newbie questions.
        >>
        >I have a huge C library which I want to be able to use in a .NET
        >application and thus am looking into writing a managed C++ wrapper for
        >in vs2005. Furthermore, this library has many callback hooks which
        >need to be implemented by the C++ wrapper.
        >>
        >These callback functions are declared as "extern C __cdecl" which I
        >am still trying to understand why. However, that is not the main
        >concern. My main question is , is there any possible way to implement
        >the callback function to point to a non-static member function rather
        >than a static function ?
        >>
        >The reason being is that I need to be able to work with multiple
        >instances of this wrapper, and if the callback functions are limited
        >to static only, then obviously I would not be able to do this.
        >>
        >I have seen some examples on the web, but those mainly deal with
        >Windows API's, and don't seem to address this sort of issue.
        >>
        >I would be interested to know if this is possible using delegates, or
        >whether it is even possible to have the C callback function call a
        >non- static member function of my C++ wrapper.
        >
        There are basically two approaches to getting into a member function of
        some class instance from a simple function pointer callback.
        >
        1. The API that uses the callback includes a "context" parameter of
        sufficient size to hold a pointer. For example, you might have
        declarations something like this:
        >
        void RegisterCallbac k(int (*cbfn)(int p1,int p2,void* context), void*
        context);
        >
        Here, a hypothetical callback registration function accepts a pointer to a
        function and an additional void* argument. When the callback is called,
        the context argument of the register function is passed to the context
        parameter of the callback function. Many Windows APIs that use callbacks
        use this pattern.
        >
        In a case like this, you can write a small "trampoline function" that
        makes the jump from a simple function to a member function:
        >
        class SomeClass(
        {
        // ...
        int Callback(int p1, int p2) { ... }
        };
        >
        int CallbackTrampol ine(int p1, int p2, void* context)
        {
        return static_cast<Som eClass*>(contex t)->Callback(p1,p2 );
        }
        >
        2. The API doesn't provide a context object (or "cookie").
        >
        In this case, the API was simply not designed to support object-oriented
        usage, so your only recourse for getting the callback to call into a
        member function involves dynamic code generation. Basically, you have to
        write code that generates the above trampoline function at runtime,
        burning the address of the object into the function. Such code is subtle
        and non-portable, but the technique is used more than one might guess.
        I believe that .NET makes this very easy, with
        Marshal.GetFunc tionPointerForD elegate, since the JIT habitually does dynamic
        code generation.
        >
        -cd
        >
        >

        Comment

        • rawhahs

          #5
          Re: Callback function from native C to C++\CLI using non-static member or delegates

          On May 24, 11:08 am, "Ben Voigt" <r...@nospam.no spamwrote:
          "Carl Daniel [VC++ MVP]" <cpdaniel_remov e_this_and_nos. ..@mvps.org.nos pam>
          wrote in messagenews:euq YSYgnHHA.588@TK 2MSFTNGP06.phx. gbl...
          >
          >
          >
          >
          >
          smm...@hotmail. com wrote:
          Before I state the problem, I just want to let the readers know, I am
          knew to C++\CLI and interop so please forgive any newbie questions.
          >
          I have a huge C library which I want to be able to use in a .NET
          application and thus am looking into writing a managed C++ wrapper for
          in vs2005. Furthermore, this library has many callback hooks which
          need to be implemented by the C++ wrapper.
          >
          These callback functions are declared as "extern C __cdecl" which I
          am still trying to understand why. However, that is not the main
          concern. My main question is , is there any possible way to implement
          the callback function to point to a non-static member function rather
          than a static function ?
          >
          The reason being is that I need to be able to work with multiple
          instances of this wrapper, and if the callback functions are limited
          to static only, then obviously I would not be able to do this.
          >
          I have seen some examples on the web, but those mainly deal with
          Windows API's, and don't seem to address this sort of issue.
          >
          I would be interested to know if this is possible using delegates, or
          whether it is even possible to have the C callback function call a
          non- static member function of my C++ wrapper.
          >
          There are basically two approaches to getting into a member function of
          some class instance from a simple function pointer callback.
          >
          1. The API that uses the callback includes a "context" parameter of
          sufficient size to hold a pointer. For example, you might have
          declarations something like this:
          >
          void RegisterCallbac k(int (*cbfn)(int p1,int p2,void* context), void*
          context);
          >
          Here, a hypothetical callback registration function accepts a pointer to a
          function and an additional void* argument. When the callback is called,
          the context argument of the register function is passed to the context
          parameter of the callback function. Many Windows APIs that use callbacks
          use this pattern.
          >
          In a case like this, you can write a small "trampoline function" that
          makes the jump from a simple function to a member function:
          >
          class SomeClass(
          {
          // ...
          int Callback(int p1, int p2) { ... }
          };
          >
          int CallbackTrampol ine(int p1, int p2, void* context)
          {
          return static_cast<Som eClass*>(contex t)->Callback(p1,p2 );
          }
          >
          2. The API doesn't provide a context object (or "cookie").
          >
          In this case, the API was simply not designed to support object-oriented
          usage, so your only recourse for getting the callback to call into a
          member function involves dynamic code generation. Basically, you have to
          write code that generates the above trampoline function at runtime,
          burning the address of the object into the function. Such code is subtle
          and non-portable, but the technique is used more than one might guess.
          >
          I believe that .NET makes this very easy, with
          Marshal.GetFunc tionPointerForD elegate, since the JIT habitually does dynamic
          code generation.
          >
          >
          >
          >
          >
          -cd- Hide quoted text -
          >
          - Show quoted text -- Hide quoted text -
          >
          - Show quoted text -
          Ben, Carl, Thanks for your replies. Ben is it possible for you to
          put up an example of how to do this using delegates ? I have seen
          some posts which do claim that this is possible to do.

          Carl,

          You are correct the API is not changeable and i am not sure if it was
          meant for object oriented programming. Therefore I am not able to
          modify it at all, and only have the .h to work with.

          Thanks to both of you for your help.

          Comment

          • Ben Voigt

            #6
            Re: Callback function from native C to C++\CLI using non-static member or delegates

            Ben, Carl, Thanks for your replies. Ben is it possible for you to
            put up an example of how to do this using delegates ? I have seen
            some posts which do claim that this is possible to do.

            >
            Carl,
            >
            You are correct the API is not changeable and i am not sure if it was
            meant for object oriented programming. Therefore I am not able to
            modify it at all, and only have the .h to work with.
            >
            Thanks to both of you for your help.
            >

            Comment

            • Carl Daniel [VC++ MVP]

              #7
              Re: Callback function from native C to C++\CLI using non-static member or delegates

              Ben Voigt wrote:
              "Carl Daniel [VC++ MVP]"
              >In this case, the API was simply not designed to support
              >object-oriented usage, so your only recourse for getting the
              >callback to call into a member function involves dynamic code
              >generation. Basically, you have to write code that generates the
              >above trampoline function at runtime, burning the address of the
              >object into the function. Such code is subtle and non-portable, but
              >the technique is used more than one might guess.
              >
              I believe that .NET makes this very easy, with
              Marshal.GetFunc tionPointerForD elegate, since the JIT habitually does
              dynamic code generation.
              Yes - I thought there was a handy .NET shortcut for it, but didn't have any
              handy .NET references at hand when I was writing. Sure makes it a lot
              easier than the all-native solutions turn out to be!

              -cd


              Comment

              Working...