I have a MFC project that provides a GUI interface for manipulating a complicated data structure (let's call it ComplicatedClass). I have a WTL project that needs to use this class a lot. I would like to be able to manage only one instance of this class and don't want each project to have its own copy of ComplicatedClass.
If I want these projects to share one instance of this class, how would I go about doing this in a safe and reliable manner? It seems like the only alternative to me is to basically have two copies of the class (one managed by the MFC project and one managed by the WTL side).
You don't need two copies. You don't mention how your application is structured, but I assume the MFC project is an .exe and the WTL one is a dll. Export a function from the dll that takes a ComplicatedClass* and store it for use in your dll. I assume here that ComplicatedClass doesn't have any UI data - i.e., no CWnd-derived objects. If it does, you'll need to be careful to wrap your HWND's properly, or stick to win32-only messaging (i.e., only use ::SendMessage).
This is just general advise, your question isn't specific enough for anything else. For example I don't see why you conclude that you have to have two copies. If you just pass a pointer from one to the other, they can both access them.
Related
Creating an ATL project in MSVC seems to create not one but two projects; the latter named the same as the former but with PS appended to its name. What is the purpose of this second project and how can I tell whether I need it?
COM supports making interface method calls across two different threads, two different processes or two different machines. This is called marshaling. Two different threads is the most common case, a COM server is often not thread-safe. COM implements thread-safety for such single-threaded coclasses by marshaling the call from the 'wrong' thread to the thread that created the server. Marshaling between processes occurs when you write an out-of-process server. Between different machines across a network is called DCOM.
This is implemented by creating an instance of the interface that looks exactly like the original. But all the methods of the interface are actually substitutes that do the job of the marshaling the call. This is the proxy. On the other end of the wire there's a substitute that looks exactly like the interface but does the opposite job. This is the stub. The proxy and stub work together to create the illusion that you're making a simple method call in your program.
The primary job of the proxy is to serialize the arguments of the method call into a memory buffer or network packet. This can be pretty untrivial, especially when you use pointers to variable-sized structures. COM needs help to get that right and that's the job of your FooPS project. When you run midl.exe on your .idl file, midl auto-generates code from the interface definitions to implement the proxy and the stub. This is quite often good enough but you may need to implement your own if the built-in keywords in IDL are not sufficient to describe your data.
Last but not least, Windows provides a standard marshaller that can marshal simple interfaces. Designed to support the sub-set of COM that's defined by COM Automation. In other words, interfaces that derive from IDispatch and only use Automation compatible types. You only need to get the registry entries right to enable it and don't otherwise need the proxy/stub generated by midl. And of course, if you only make simple in-process calls on one thread then you won't need it either. This is pretty common.
As #ebutusov said, *PS project contains implementations for Proxy and Stub. They are not standard, instead they are generated by MIDL for interfaces exported from your ATL server. These interfaces are declared in the *.IDL file. The ouput of the project is DLL. You may read this article to get more details.
You may remove PS project from the solution in case if you do not define any custom interfaces in you *.IDL file or if you define only interfaces which have dual and oleautomation modifiers. In that case a standard typelib marshaller will be used.
In order to be able to make use of the standard typelib marshaller, one has to register a typelibrary (which is done automatically since you are using ATL)
It's proxy/stub code, which contains non-standard data marshallers needed to transfer data between different apartments (threading related). It's used when application, which calls your COM object, uses different COM threading model. There was an option in ATL/COM wizard to merge this code into main library. In many common scenarios you don't have to worry about it (i.e. when your COM dll runs in the client context), unless you want to write a custom marshaller.
I have a rather large code base that is highly modular (lots and lots of plugins), and very often need to pass strings and such between modules. For reference, the code:
only compiles in MSVC/Visual Studio, and very clearly does not and will not support other compilers. Supporting them is not a concern.
only runs on Windows, and very clearly does not and will not support other OSes. Same as above.
all modules will be Windows PEs of some sort; assume the same bitness and that they're built for the same platform.
there are a few spots where MFC is easier to use, a few where STL is. There's a very good chance both will be used within each module.
The question is only regarding passing objects between modules.
Now, I'm under the impression that passing STL objects between modules can really break, if the library or compiler versio changes. Particularly when it comes to dtors and destroying objects outside of the module/version they were created in.
Is MFC any safer in that way? Can you pass a MFC object (a CString for example) from Base.dll to Plugin.dll safely? Do you have to pass a pointer, can you not safely delete it from the plugin?
Does it matter if MFC is statically linked or used from a DLL?
MSDN mentions in a few places that:
All memory allocations within a regular DLL should stay within the DLL; the DLL should not pass to or receive from the calling executable any of the following:
pointers to MFC objects
pointers to memory allocated by MFC
If you need to do any of the above, or if you need to pass MFC-derived objects between the calling executable and the DLL, then you must build an extension DLL.
However, the page extension DLLs mention they are intended primarily for implemented objects derived from MFC objects. I have no interest in doing that, just using them and passing between various modules.
Does passing shared_ptrs change anything (or a class with a virtual dtor)?
Is there a solution to this without resorting to C types?
An extension DLL will share the MFC DLL with the application and any other extension DLLs, so that objects may be passed freely between them. Microsoft may have intended for extension DLLs to implement extended classes, but that's not a requirement - you can use it any way you want.
The biggest danger with the standard library is that so much of it is based on templates. That's dangerous, because if the DLL and application are built with different versions of the templates you run against the One Definition Rule and undefined behavior bites you in the rear. This is not just initialization or destruction of the object, but any operation against the object whatsoever!
You can declare COM-like abstruct-method only interfaces and pass interface instead. For example write a factory method like WMCreateReader that create an object (whether it is MFC based or has STL members does not need to be exposed to the caller) and return its interface.
I'm working on a project which has multiple similar code paths which I'd like to separate from the main project into plugins. The project must remain cross-platform compatible, and all of the dynamic library loading APIs I've looked into are platform specific.
What's the simplest way to create a dynamic library loading system which can be compiled and run on multiple operating systems without extra modification of the code? Ideally, I'd like to write one plugin, and have it work on all the operating systems the project supports.
Thanks.
You will have to use platform dependent code for the loading system. It's different loading a DLL on Windows than loading a shared object in Unix. But, with a couple of #ifdef you will be able to have mostly the same code base in the loader.
Having said that, I think you can make your plugins platform independent. Of course, you will have to compile it for every platform, but the code will be 99% the same.
Dynamic library loading an Windows and Unix/Linux works with 3 functions. A pair of functions to load/unload the libraries, and another function to get the address of a function in the library. You can easily write a wrapper around these three functions to provide cross operating systems suppport.
Ideally, I'd like to write one plugin, and have it work on all the operating systems the project supports.
Few things from top of my head:
Avoid static objects in the dynamic libraries. Provision proper initialization methods/functions to allocate the objects. The issues which occur during library being loaded by the OS (this is when the c'tors for static objects are called) are very hard to debug - next only to the multi-threading issues.
Interface headers may not contain code. No inline methods, no preprocessor defines. That is to avoid tainting application with the code from particular version of library, making it impossible to replace the library at later time.
Interface headers may not contain implementation classes themselves - only abstract classes and factory functions. Similar to the previous point - to avoid application depend on the particular version of the classes. Factories are needed as a way for user application to instantiate the concrete implementation classes.
When introducing new version of an interface, to keep things somehow backward compatible, do not modify existing abstract class - create new abstract class inherited from it and add new methods there. Change factory to return the new version. (Recall MS' IInterface, IInterface2, IInterface3 and so on.) In the implementation, use newer version of the abstract class. That by polymorphism would make the implementation backward compatible with the older interface versions. (That obviously calls for periodic interface maintenance and clean-ups - to remove the old cruft.)
Take a look at the boost.extension library, it is not really part of boost, but you can find it in the sandbox. It is kind of frozen also, but overall the library is stable and easy to use.
Some classic Windows/C++ applications can't easily be moved to managed C++.net, due to use of external libraries. Is it feasible to use newer GUI libraries like winforms (or even WPF) with such applications, 'dropping in' new controls to replace stale-looking MFC?
Or is it not really worth it, and would take a lot of time?
I've found that C++/CLI is very capable. Are you actually running into problems? It should be able to compile your MFC project directly.
But mixing WinForms and MFC within the same thread could be difficult as they both want to run their own message loop. As Ray Burns has suggested, WPF may be more cooperative with MFC.
Because of IJW it's quite easy to use WinForms or WPF from unmanaged code. More lilkely, though, you'll want to write the new components in managed code and just embed them in your unmanaged application. That means that for all the new stuff you won't have to deal with memory management, etc.
WPF is much more powerful and nicer to use than WinForms, so I would definitely bypass WinForms if you haven't been using it already.
One consideration is you'll want to take advantage of the data binding power of WPF. To do this you'll need to expose your unmanaged data as COM classes or copy the data into managed code. An easy way to do this is to write managed wrapper classes in C++ that access the unmanaged data. Another easy way is to directly access the business object layer (or database) from managed code. It depends on exactly what your current data layer looks like.
A better approach would be to create a new .NET project (C# is your friend) for your UI, and reference your C++ DLLS from there. You're not going to have an easy time mixing managed and unmanaged code in a single project.
See How do I call unmanaged C/C++ code from a C# ASP.NET webpage. It talks about a web page specifically, but the code is identical for a winForms or WPF app.
It's not really worth it, and it would take a huge amount of time.
It's possible to have unmanaged C++ code host the CLR, and to have the managed code run the UI.
But, it's definitely not a trivial task.
An easier approach would be to rewrite the unmanaged code a bit to be invokable via P/Invoke or COM interop, and have a managed app (with winforms) call the unmanaged code.
I've seen with Microsoft COM and XPCOM, at least from what I've read and gathered so far, that the implementations of interfaces in a component have to essentially be in the single class that derives all the virtual interfaces. Is this correct? What am I missing?
Is there a way to have multiple objects (possibly in separate DLL's) each provide their functionality and still be able to freely transition between them using QueryIterface?
What I'm looking for is to have a component with some functionality, but still allow external client code to create new extensions of the component with (possibly) new interfaces. Ideally this should happen without divulging the current source of the component and its implementation.
This should be possible, although probably not supported by the standard high-level wrappers. Most of the wrappers (ATL, MFC, etc.) only support mapping a COM object to a single class. However, QueryInterface is allowed to return a different pointer and calls COM object code, so the first COM object could load a different DLL, instantiate a different object, and return a pointer to it's interface (vtable).
It's all possible as far as I know, you'll just likely be writing a lot of the low-level glue code yourself.
Yes, ATL supports tear-off interfaces
This allows to imlement the interface in another class that is instantiated only when the interface is requested. Since it passes only an interface, I guess it can be put into a separate DLL, too.
(can also be cached after being requested once)