[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.interop

Callback to unmanaged code

Paul S

9/3/2007 7:00:00 AM


Hi

I have a legacy product written in C++ with a class - Protocol -
containing a method - int Send(LPCTSTR data). I would like to call managed
code with this
funtion as a callback. The Idea is that managed code is given a filename
which it then
open, process and send it back to a client via callbacks to the C++ code's
send method.

To avoid having to change my legacy code and compile it with /clr option I
have built a
Win32 API to use as a layer between to managed and unmanaged code.

So far my model is something like this

in C++:
typedef int(__stdcall * PFN_Send)(LPCTSTR);

calls FileTransfer_Transfer((PFN_Send)protocol->Send, fileName) in the Win32
API

In Win32 API:
typedef int (__stdcall *ProtocolSendCB)(LPCTSTR);

int WINAPI FileTransfer_Transfer(PFN_Send callback, LPCTSTR fileName)
Converts the functionpointer PFN_Send to ProtocolSendCB

In managed:
public delegate int SendCallBack(string data);
Class FileTransfer

Method to be called: Transfer(SendCallBack cb, string fileName)

--
Paul S
9 Answers

wawang

9/3/2007 11:13:00 AM

0

Hi Paul,

I've carefully reviewed your question but I'm still unclear about some
points:

1) Is the legacy product a standalone application or a DLL?
2) Is your to-be-written Win32 API reside in the same module as the legacy
product or a separate DLL?

Without these information, I'm not sure if your objective here can be
achieved using the approach like how we use P/Invoke to call Win32 API that
requires a callback, such as EnumWindows:

http://www.pinvoke.net/default.aspx/user32/EnumWi...


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

Paul S

9/3/2007 1:58:00 PM

0

Hi Walter
The legacy C++ module and the Win32 API are 2 separate dll's
--
Paul S


""Walter Wang [MSFT]"" wrote:

> Hi Paul,
>
> I've carefully reviewed your question but I'm still unclear about some
> points:
>
> 1) Is the legacy product a standalone application or a DLL?
> 2) Is your to-be-written Win32 API reside in the same module as the legacy
> product or a separate DLL?
>
> Without these information, I'm not sure if your objective here can be
> achieved using the approach like how we use P/Invoke to call Win32 API that
> requires a callback, such as EnumWindows:
>
> http://www.pinvoke.net/default.aspx/user32/EnumWi...
>
>
> Regards,
> Walter Wang (wawang@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>

wawang

9/4/2007 9:29:00 AM

0

Hi Paul,

Sorry for asking you for more information again, but I'm not sure if I've
fully understood the question.

Per your initial message, you said you need to callback into the
*unmanaged* code; however, since the .NET code is the caller, the unmanaged
code is in a DLL, then I think this is not *callback* into unmanaged, it's
actually .NET *calls* unmanaged code. If this is the case, then I think you
don't need to define a delegate in .NET: you simply use P/Invoke to call
the win32 API FileTransfer_Transfer. (If you do use a delegate in
FileTransfer.Transfer, then you simply create a .NET function with the
signature of the delegate and calls the API in this function). However, in
this case, I'm not sure how you will make sure the class in C++ DLL get
instantiated?

On the other hand, if you need to callback into *managed* code from
unmanaged code, then you may find following article useful:

#David Notario's WebLog : Gotchas with Reverse Pinvoke (unmanaged to
managed code callbacks)
http://blogs.msdn.com/davidnotario/archive/2006/01/13/5...


I really hope I haven't misunderstood anything. If I do, please feel free
to correct me and tell me more about your application. Thanks.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

Paul S

9/4/2007 11:34:00 AM

0

Hi Walter
The C++ module calls managed code.
The managed code must perform callbacks to the C++ module to call the function

typedef int(__stdcall * PFN_Send)(LPCTSTR);

I therefore beleive the call to managed code must contain a pointer to the
PFN_Send function.

--
Paul S


""Walter Wang [MSFT]"" wrote:

> Hi Paul,
>
> Sorry for asking you for more information again, but I'm not sure if I've
> fully understood the question.
>
> Per your initial message, you said you need to callback into the
> *unmanaged* code; however, since the .NET code is the caller, the unmanaged
> code is in a DLL, then I think this is not *callback* into unmanaged, it's
> actually .NET *calls* unmanaged code. If this is the case, then I think you
> don't need to define a delegate in .NET: you simply use P/Invoke to call
> the win32 API FileTransfer_Transfer. (If you do use a delegate in
> FileTransfer.Transfer, then you simply create a .NET function with the
> signature of the delegate and calls the API in this function). However, in
> this case, I'm not sure how you will make sure the class in C++ DLL get
> instantiated?
>
> On the other hand, if you need to callback into *managed* code from
> unmanaged code, then you may find following article useful:
>
> #David Notario's WebLog : Gotchas with Reverse Pinvoke (unmanaged to
> managed code callbacks)
> http://blogs.msdn.com/davidnotario/archive/2006/01/13/5...
>
>
> I really hope I haven't misunderstood anything. If I do, please feel free
> to correct me and tell me more about your application. Thanks.
>
>
> Regards,
> Walter Wang (wawang@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>

wawang

9/6/2007 6:11:00 AM

0

Hi Paul,

Thank you for your waiting.

So the key issue here is how to call a function pointer returned from
unmanaged code in C#, right?

I've spent much time on this but unfortunately it turns out it's not
possible in C# to cast the function pointer into a delegate and call it
from managed code.

A workaround is to pass the function pointer (of IntPtr data type in C#) to
the Win32 API wrapper DLL and let it call the function instead.

I've also found a related example on this issue and with the above
workaround:

#Enumerate and Host Control Panel Applets using C#. - The Code Project - C#
Programming
http://www.codeproject.com/csharp/applet...

Hope this helps. Please feel free to let me know if there's anything else I
can help.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.




Christian Fröschlin

9/6/2007 7:47:00 AM

0

Walter Wang [MSFT] wrote:

> I've spent much time on this but unfortunately it turns out it's not
> possible in C# to cast the function pointer into a delegate and call it
> from managed code.

What's wrong with Marshal.GetDelegateForFunctionPointer (.NET 2.0)?

Paul S

9/6/2007 12:02:00 PM

0


I've read the article and I'll have to read it again.

The problem with the article and all other articles I've read so far is that
they deal with win32 dll that are loaded after the call. I have the call to
perform the callback to in the code making the origianl code

I hvae made a test sample - a cpp console app.


#include "stdafx.h"
#include "..\Win32Api\Win32Api.h"

typedef int(__stdcall * PFN_Write)(LPCTSTR);

int WriteOnConsole(LPCTSTR pszText)
{
return wprintf_s(pszText);
}

int Unmanaged_Run()
{
int i = 0;
for (int i = 0; i < 10; i++)
{
TCHAR szBuf[100];
swprintf_s(szBuf, L"Text from unmanaged: %d\n", i);
WriteOnConsole(szBuf);
}
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
WriteOnConsole(L"Calling un-managed ");
Unmanaged_Run()

WriteOnConsole(L"Calling managed ");
Managed_Run((PFN_Write)WriteOnConsole);

return 0;
}

I want the code executed in the Unmanaged_Run function to be executed in
managed code and the console app cannot be compiled with the /clr swith.

Just like in the article I have also implemented a Win32 library in c++
compiled with the /clr switch to put between the managed and unmanaged world.
The function skeleton looks like this:

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace ManagedEnviroment;

// what should this look like
int WINAPI Managed_Run(PFN_Write callback)
{
TestEngine engine;
try
{
engine = new TestEngine();
}
catch (Exception * ex)
{
String * msg = ex->Message;
Console::WriteLine(msg);
return 0;
}
try
{
// how do I make this
return engine->Run((__gc * )(PFN_Write)callback);
}
catch (Exception * ex)
{
String * msg = ex->get_Message();
Console::WriteLine(msg);
return -1;
}
return 0;
};

Hope this clarifys a bit more

Regards
Paul S

--
Paul S


""Walter Wang [MSFT]"" wrote:

> Hi Paul,
>
> Thank you for your waiting.
>
> So the key issue here is how to call a function pointer returned from
> unmanaged code in C#, right?
>
> I've spent much time on this but unfortunately it turns out it's not
> possible in C# to cast the function pointer into a delegate and call it
> from managed code.
>
> A workaround is to pass the function pointer (of IntPtr data type in C#) to
> the Win32 API wrapper DLL and let it call the function instead.
>
> I've also found a related example on this issue and with the above
> workaround:
>
> #Enumerate and Host Control Panel Applets using C#. - The Code Project - C#
> Programming
> http://www.codeproject.com/csharp/applet...
>
> Hope this helps. Please feel free to let me know if there's anything else I
> can help.
>
>
> Regards,
> Walter Wang (wawang@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>
>
>
>

wawang

9/7/2007 9:57:00 AM

0

Hi Paul,

Thanks for your update and detailed code example.

Normally we prefer to keep the discussion in newsgroup, however, since
we've made little progress on this post so far, I would like to take it
offline. Would you please email me privately when you see this? Of course
we will post the summary here when we solve the issue in the end. Thanks!


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

Doug Semler

9/7/2007 3:23:00 PM

0

On Sep 6, 3:47 am, Christian Fr?schlin <froesch...@mvtec.com> wrote:
> Walter Wang [MSFT] wrote:
> > I've spent much time on this but unfortunately it turns out it's not
> > possible in C# to cast the function pointer into a delegate and call it
> > from managed code.
>
> What's wrong with Marshal.GetDelegateForFunctionPointer (.NET 2.0)?

Except when the function is not _stdcall <g>