2

I have a working unmanaged C++ DLL which is attached to my C# code using p/invoke

    [DllImport("p2p.dll", EntryPoint = "Start")]
    public static extern void Start();

    [STAThread]
    static void Main()
    {
        Thread th= new Thread(Start);
         th.Start();
....

This way i can retrieve information from my C++ code, but if my C++ code needs to trigger a C# function then how do i do it in a smart way rather than putting all request in a queue and checking it from C# in a thread.

Navin
  • 554
  • 2
  • 9
  • 31

3 Answers3

2

You can either use Managed C++, or initialize your C++ library from C# by passing it a set of function pointers (delegates on the managed side) to all relevant entry points.

At the start of your program call the initializer:

[DllImport("p2p.dll")]
public static extern void Initialize(Action triggerManagedAction);

Initialize(() => {Console.WriteLine("called from C++");});

And in the C++ implementation of that function, remember the function pointer.

Please also read the comment by Hans Passant and Google this technique before using it. I is easy to introduce bugs here.

usr
  • 168,620
  • 35
  • 240
  • 369
  • Thank, i cant use Managed C++, but can you elaborate more on what you said second regarding function pointers – Navin Aug 20 '12 at 12:16
  • 1
    Sure. I added some sample code. You have to research the C++-side yourself because I' don't know enough about that aspect. – usr Aug 20 '12 at 12:17
  • 3
    The code snippet is very dangerous and easily leads to a crash when the garbage collector destroys the delegate object. It must be stored in a field to stay alive. It is also best to declare the delegate type separately so that the calling convention can be specified explicitly. The posted snippet requires __stdcall on the function pointer to work properly. – Hans Passant Aug 20 '12 at 12:45
  • @HansPassant, I now refer to your very important comment from my answer. Btw, feel free to edit my post. – usr Aug 20 '12 at 12:52
  • @usr onus is on you rather than Hans to fix the post – David Heffernan Aug 20 '12 at 17:55
  • hey @usr my Initialize(()... says "Method must have a return type." Navin did you get this to work? thks – StinkyCat Jan 28 '13 at 16:25
1

You can do it by creating a Managed C++ class, that acts as a proxy between your C++ and .Net event handlers. Here is how it looks:

  • Suppose that you register notifications for the C++ class with, by publishing a, say, ICEventHandler interface, whose notify() method will be called.
  • In managed C++ create a class, derived from ICEventHandler, that has a delegate, called for example Notify(). In the inherited ICEvenhHandler.notifty() call the Notify delegate.
  • Having a .net Nofity method, construct an instance of your proxy class, and pass that for the C++ event source class

This way a C++ event will fire your .Net Notify method.

Lorlin
  • 844
  • 5
  • 15
  • okay.., i guess the problem here will be when i implement the bridge between unmanaged and managed isnt it? because i cannot compile my code as managed, yes i can refence the unmanged to a managed C++, but isnt that a long process and the DLL is a network layer so wont it get slow down. – Navin Aug 20 '12 at 12:32
  • 1
    The managed c++ bridge can reference the C++ dll library, and will produce a .net assembly, that can be referenced from any .net project. We did this, and was not notably slow, however other interprocess communication means might be faster (Named Pipes, Sockets, etc.) – Lorlin Aug 20 '12 at 12:40
  • Thank you, Ill look in to it and let you know :) – Navin Aug 20 '12 at 13:04
  • I hope you mean C++/CLI, not "Managed Extensions for C++". – Ben Voigt Aug 20 '12 at 13:20
0

One of the ways would be compiling your C++ code with a /clr flag. Couple different examples can be found in this SO thread.

Community
  • 1
  • 1
Dmitriy
  • 1,852
  • 4
  • 15
  • 33
  • i am using boost/asio and boost/thread so i cannot compile it with /clr. Its possible to compile boost in /clr but in my case its kind of complex. – Navin Aug 20 '12 at 12:14