views:

79

answers:

4

Hello,

I need to add a new component to a C++ Win32 application (no CLR support) and I would like to implement the new component in C# and use WPF. This new component is basically a window with some controls, which I need to launch quickly from an option in the menu of the Win32 application. The new component and the existing application share some int values and both can modify these values and the other should be notified of changes.

What would be the best way to achieve this?

Thanks

+1  A: 

Have you seen the MSDN docs on this subject?

A cursory read implies this is not possible without enabling /clr on your C++ code. if you are able to move to this model then the things you want seem do-able.

btw I would not implement update/signalling code on both sides of the managed/unmanaged boundary for your shared data. Decide where the data lives, and have that code provide a) thread-safe accessors and b) 'update event' wiring that are used by whoever needs to write the data and know about updates.

Check out Observer pattern for a description of how to implement notification to multiple consumers. This may be overkill for your case but useful background.

EDIT:

Until you get the two modules coresident, discussion of event notification design seems premature. If you really cannot build your native code with /clr then I don't see how your WPF component can be used without a separate process, and resulting complexity in interaction and performance hit. Can you re-implement this WPF functionality in native code?

On the other hand - if you plan on making more mods to this codebase, perhaps it's worth considering how hard it would be to port the native code to be /clr-ready. Inline assembler does not prevent use of /clr but it does make it harder, as I am sure you have seen here. My guess is that this would be less work than wiring up the WPF code externally.

The path of least resistance at this point may be to replicate your WPF component in native code. Long term taking the pain of converting your app to /clr may provide a better foundation though. Sorry there is no simple answer.

Steve Townsend
Yes, I know the MSDN link you suggested. The problem here is that I cannot switch the existing code to /clr (inline assembly code, /MT). As for the Observer pattern, I perfectly agree with using it. I was more interested in how the actual communication should occur between the two modules (events, callbacks).
tiz
See edited response. Not an easy problem :-(
Steve Townsend
COM interop was better suited for my scenario. Porting the native code to support /clr might be better for future extensions. Thanks
tiz
Glad that worked out.
Steve Townsend
A: 

One way to achieve this is compile your C++ application as a C++/CLI application. Once it's a C++/CLI app, you can mix managed and native code easily, and even talk to managed components with ease.

Judah Himango
I can't compile it to C++/CLI.
tiz
+1  A: 

If you want to do this without changing your C++ compilation you might look at calling the .NET assembly as via COM. MSDN describes how to expose .NET Framework Components to COM.

The way I've done this is basically:

  1. Make a COM friendly class and interface in C#
  2. Export the TLB from the DLL
  3. GAC the DLL
  4. Register the DLL using regasm.exe
  5. #import the TLB into my C++ code
  6. CoCreateInstance using the __uuidof my C# class

However I haven't tried to do this with a UI component. If the WPF form is a modal dialog you should be OK. If not then I don't know if WPF will be happy with your message loop; you may need to give it a seperate thread so it can run its own loop.

Justin R
I'll look into this. Thanks
tiz
This worked for me. Here's a [sample](http://cid-fd9a0f1f8dd06954.skydrive.live.com/self.aspx/Public/Code%20Samples/WPF/WpfComInterop.zip) I used to get started, if anyone else needs this.
tiz
A: 

Rather than mess with COM, I'd prefer to use C++/CLI as a glue layer - that does not require recompiling your entire app as C++/CLI.

That means:

  1. Write the C# code you want.
  2. Write a thin C++/CLI wrapper. This can reference (i.e. dynamically link) to the C# app. All it does is expose a native API around the .NET API. It takes some getting used to, but you can do pretty complex stuff here, including fairly fancy automagic interop via marshal_as. You'll compile this into a dll - a mixed mode DLL.
  3. Your main app now links dynamically to the mixed mode DLL and includes the headers for its API. It can call functions as usual.

This is quite a bit nicer that COM, I think: it doesn't require the GAC, it has a lower overhead should performance ever matter, and exchanging complex datastructures including callbacks & deep object graphs is possible (though there is a learning curve here) quite cleanly by adding custom marshal_as templates/overloads.

Eamon Nerbonne
How can this be more performant if it involves by-passing one more DLL? You can exchange callbacks through COM interop, too: [Marshal.GetDelegateForFunctionPointer](http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.getdelegateforfunctionpointer.aspx). Didn't need to exchange more complex data structures, though.
tiz