tiz
tiz

Reputation: 90

Extending C++ Win32 application with a C# WPF component

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

Upvotes: 2

Views: 1538

Answers (4)

Eamon Nerbonne
Eamon Nerbonne

Reputation: 48066

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.

Upvotes: 0

Steve Townsend
Steve Townsend

Reputation: 54128

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.

Upvotes: 1

Justin R
Justin R

Reputation: 381

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.

Upvotes: 1

Judah Gabriel Himango
Judah Gabriel Himango

Reputation: 60001

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.

Upvotes: 0

Related Questions