Callbacks from unmanaged code...

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • cada0310

    Callbacks from unmanaged code...

    Hi there,

    I'm new to C# (but not to C++), and I'm trying to create a web service that
    calls some of our older software, located in a DLL. I'm getting most the
    calls to work ok, but one of them needs a callback into the managed code. I
    thought I had it all worked out, but it seems like when the callback is
    getting hit, things might be going out of scope and crashing the app.

    Here's my little web service function; I hacked out a bunch of other stuff
    for brevity, but the general idea is, I call the "Initialize " function,
    providing a callback to the DLL so the DLL can call me when certain
    operations in the "LoginUser2 " complete.

    You can see where I tried to keep the callback around in a session object,
    but, being a novice, I'm not sure this is the right approach. Essentially, I
    need this callback alive for the whole life of the user's session.

    [WebMethod(Enabl eSession = true)]
    public string HelloArguments( string sLogin, string sPassword)
    {
    Test.TNInitiali zeCallbackType cb = new
    Test.TNInitiali zeCallbackType( Test.TNAPICallb ack);
    Session["Callback"] = cb;

    hWho = Test.Initialize (cb);

    result2 = Test.LogonUser2 (hWho, sLogin, sPassword);

    return sResult;
    }

    and some defs:

    class Test
    {
    [DllImport("mydl l.dll")]
    public static extern Int32 LogonUser2(IntP tr hWho, string pszLogin,
    string pszPassword);

    public delegate IntPtr TNInitializeCal lbackType(IntPt r hWho, Int32
    a1, Int32 a2, Int32 a3);

    [DllImport("mydl l.dll")]
    public static extern IntPtr Initialize(TNIn itializeCallbac kType
    callback);

    public static IntPtr TNAPICallback(I ntPtr hWho, Int32 a1, Int32 a2,
    Int32 a3)
    {
    return (IntPtr)0;
    }

    Thanks for any help or pointers as to where I can read up on this.

  • rmacias

    #2
    RE: Callbacks from unmanaged code...

    In .NET, the calling convention for methods is StdCall. What is the calling
    convention for your unmanaged *.dll? I'm assumming it is probably cdecl,
    which will cause problems in your managed callback. The stack is probably
    being popped one too many times after your call back executes.

    You can use the CallingConventi on property of the DllImport attribute to
    define the calling convention for that method, but I'm not sure if this can
    be applied to delegates.

    [DllImport("mydl l.dll", CallingConventi on=CallingConve ntion.Cdecl )]
    public static extern IntPtr Initialize(TNIn itializeCallbac kType callback);

    Not sure if the above code will work for a delegate, but you can give it a
    shot. If you have the unmanaged souce code, you can probably create another
    method called something like "InitializeStdC all" using the StdCall calling
    convention and then in there, call "Initialize ". This will act as a wrapper.

    Hope this helps or points you in the right direction.

    "cada0310" wrote:
    [color=blue]
    > Hi there,
    >
    > I'm new to C# (but not to C++), and I'm trying to create a web service that
    > calls some of our older software, located in a DLL. I'm getting most the
    > calls to work ok, but one of them needs a callback into the managed code. I
    > thought I had it all worked out, but it seems like when the callback is
    > getting hit, things might be going out of scope and crashing the app.
    >
    > Here's my little web service function; I hacked out a bunch of other stuff
    > for brevity, but the general idea is, I call the "Initialize " function,
    > providing a callback to the DLL so the DLL can call me when certain
    > operations in the "LoginUser2 " complete.
    >
    > You can see where I tried to keep the callback around in a session object,
    > but, being a novice, I'm not sure this is the right approach. Essentially, I
    > need this callback alive for the whole life of the user's session.
    >
    > [WebMethod(Enabl eSession = true)]
    > public string HelloArguments( string sLogin, string sPassword)
    > {
    > Test.TNInitiali zeCallbackType cb = new
    > Test.TNInitiali zeCallbackType( Test.TNAPICallb ack);
    > Session["Callback"] = cb;
    >
    > hWho = Test.Initialize (cb);
    >
    > result2 = Test.LogonUser2 (hWho, sLogin, sPassword);
    >
    > return sResult;
    > }
    >
    > and some defs:
    >
    > class Test
    > {
    > [DllImport("mydl l.dll")]
    > public static extern Int32 LogonUser2(IntP tr hWho, string pszLogin,
    > string pszPassword);
    >
    > public delegate IntPtr TNInitializeCal lbackType(IntPt r hWho, Int32
    > a1, Int32 a2, Int32 a3);
    >
    > [DllImport("mydl l.dll")]
    > public static extern IntPtr Initialize(TNIn itializeCallbac kType
    > callback);
    >
    > public static IntPtr TNAPICallback(I ntPtr hWho, Int32 a1, Int32 a2,
    > Int32 a3)
    > {
    > return (IntPtr)0;
    > }
    >
    > Thanks for any help or pointers as to where I can read up on this.
    >[/color]

    Comment

    • cada0310

      #3
      RE: Callbacks from unmanaged code...

      Hi - thanks for your response!

      The definition is actually __stdcall in the unmanaged code; here's the C++
      prototype definition for the callback that has to be passed to C++:

      typedef long (*TNAPI_CALLBAC K)(HANDLE, DWORD, DWORD, DWORD);
      HANDLE CALLBACK TN_Initialize(T NAPI_CALLBACK pFunc);

      So the idea is that in C# I need to call TN_Initilalize and pass it a
      callback function, so that the unmanaged DLL can make calls to the provided
      callback.

      It seems to be (mostly) working; I can set breakpoints in the C# provided
      callback, and it's getting called...but I think something's munged because
      sometimes the app just croaks.


      "rmacias" wrote:
      [color=blue]
      > In .NET, the calling convention for methods is StdCall. What is the calling
      > convention for your unmanaged *.dll? I'm assumming it is probably cdecl,
      > which will cause problems in your managed callback. The stack is probably
      > being popped one too many times after your call back executes.
      >
      > You can use the CallingConventi on property of the DllImport attribute to
      > define the calling convention for that method, but I'm not sure if this can
      > be applied to delegates.
      >
      > [DllImport("mydl l.dll", CallingConventi on=CallingConve ntion.Cdecl )]
      > public static extern IntPtr Initialize(TNIn itializeCallbac kType callback);
      >
      > Not sure if the above code will work for a delegate, but you can give it a
      > shot. If you have the unmanaged souce code, you can probably create another
      > method called something like "InitializeStdC all" using the StdCall calling
      > convention and then in there, call "Initialize ". This will act as a wrapper.
      >
      > Hope this helps or points you in the right direction.
      >
      > "cada0310" wrote:
      >[color=green]
      > > Hi there,
      > >
      > > I'm new to C# (but not to C++), and I'm trying to create a web service that
      > > calls some of our older software, located in a DLL. I'm getting most the
      > > calls to work ok, but one of them needs a callback into the managed code. I
      > > thought I had it all worked out, but it seems like when the callback is
      > > getting hit, things might be going out of scope and crashing the app.
      > >
      > > Here's my little web service function; I hacked out a bunch of other stuff
      > > for brevity, but the general idea is, I call the "Initialize " function,
      > > providing a callback to the DLL so the DLL can call me when certain
      > > operations in the "LoginUser2 " complete.
      > >
      > > You can see where I tried to keep the callback around in a session object,
      > > but, being a novice, I'm not sure this is the right approach. Essentially, I
      > > need this callback alive for the whole life of the user's session.
      > >
      > > [WebMethod(Enabl eSession = true)]
      > > public string HelloArguments( string sLogin, string sPassword)
      > > {
      > > Test.TNInitiali zeCallbackType cb = new
      > > Test.TNInitiali zeCallbackType( Test.TNAPICallb ack);
      > > Session["Callback"] = cb;
      > >
      > > hWho = Test.Initialize (cb);
      > >
      > > result2 = Test.LogonUser2 (hWho, sLogin, sPassword);
      > >
      > > return sResult;
      > > }
      > >
      > > and some defs:
      > >
      > > class Test
      > > {
      > > [DllImport("mydl l.dll")]
      > > public static extern Int32 LogonUser2(IntP tr hWho, string pszLogin,
      > > string pszPassword);
      > >
      > > public delegate IntPtr TNInitializeCal lbackType(IntPt r hWho, Int32
      > > a1, Int32 a2, Int32 a3);
      > >
      > > [DllImport("mydl l.dll")]
      > > public static extern IntPtr Initialize(TNIn itializeCallbac kType
      > > callback);
      > >
      > > public static IntPtr TNAPICallback(I ntPtr hWho, Int32 a1, Int32 a2,
      > > Int32 a3)
      > > {
      > > return (IntPtr)0;
      > > }
      > >
      > > Thanks for any help or pointers as to where I can read up on this.
      > >[/color][/color]

      Comment

      Working...