Current setup:
Windows C++ native Application provides a COM interface that is used (RPC style, simple function calls) by a number of plugin executables. Communication is only on the local machine.
[App.exe (COM server)] <-> [plugin1.exe (COM client / possible callbacks etc.)]
<-> [plugin2.exe (COM client)]
We would now like to replace the COM interface with something else for selected plugins.
What options do we have for local "RPC style" IPC that would be as easy to use as COM?
The following restrictions apply:
Performance must be at least as good as local COM calls. (In light of Steve's answer, any alternative that wouldn't perform significantly worse than local out-of-process COM calls would already be helpful!)
The interface should be easy to use. No explicit fiddling around with memory and raw sockets while using the interface in the clients or the server.
native C++ on windows
Performance between processes will never match local COM to an in-process server, since in-process COM calls reduce to a simple function call on the calling thread. For inter-process traffic, there is ALWAYS going to be marshaling and context switching overhead that makes this slower.
Taking that one step further, it's unlikely you will build anything as simple as what you have with COM that performs anything like as well as COM. For local out-of-process servers, COM will run over an optimized RPC stack called LRPC.
Related
I'm not expert in Component Object Model (COM), but from what I understand it works something like this:
Program A (a "server" program) exposes COM interface lets say via TLB file.
A client program uses this interface and call it's functions (and all the underlying stuff is done for you free of charge).
So in this case when the "Server" program is running and "Client" program communicates with the "Server" using COM object.
Each one of the programs (processes) has it own address space.
Now with MSXML it is a bit different.
From what I understand, msxmlX.dll is a COM dll, but lets say when I implicitly link against it (using msxmlX.h and msxmlX.lib) during run time it's being loaded to the same memory space as my executable.
So, in this case WHY COM object being used when there is clearly no IPC going on (both msxml.dll and "my app" are using the same memory and can "communicate" as simple as calling a function) ???
You can create COM objects either in process, out of process, or on another machine completely. The choice of which depends on what your requirements are.
COM is designed to make software components reusable and language independent.
It's not just a mechanism to facilitate IPC as you assume.
I am dealing with a single-threaded library (not thread safe) that I want to wrap in a COM out-of-process object to get around its thread non-safety. I need a behavior where each new COM object is instantiated in its own process - some form of out-of-process singleton.
It's been a while since I've been dealing with hardcore COM so I am not sure how to approach this or whether this is at all possible without some trickery.
Call CoRegisterClassObject() with the REGCLS argument set to REGCLS_SINGLEUSE. Beware of the cost, a process is not a cheap operating system object.
There is otherwise no reason why you couldn't ensure that marshaled method calls are thread-safe, just call CoInitializeEx() to ask for an STA. Works as well in a out-of-process server as it does in a in-process server. If you are only doing this to solve a threading problem then definitely favor in-process STA. Message loop required.
I have a very simple interface which needs to communicate between processes. It's currently implemented in a very simple manner (all single proc):
bool GetFoo(struct Foo *outFoo);
bool GetBar(struct Bar *getBar);
Such as:
Foo foo;
if (!GetFoo(&foo))
{
ReportError();
}
GetFoo fills out the "Foo" data structure with pure data (that is, no pointers - it's purely blitable data).
I need to convert this in-process function call to be between two processes on the same machine (in this case it's always the same machine). Is there a commonly followed idiom for cross-process calls in C++ on Windows? Is there some kind of intra-process communication supported by Windows? Should I be using shared memory instead?
One note: I don't want to take a dependency on anything other than the Windows APIs if at all possible.
You have many choices, but in my personal experience the most popular/easy to use ones are: sockets & pipes.
See here for all IPC options available for Windows.
I'm not sure what the most common is -- to truly answer that we'd have to have some kind of polling. That said, the most flexible way would probably be to expose the methods via DCOM.
A common method would be RPC, it can be implemented in various ways for instance as Billy mentioned using COM` (or DCOM if the processes are residing on different machines).
Although you may want to think about not doing direct RPC calls and instead have a named pipe between your processes which is used for the communication.
There are a number of ways to communicate between processes on the same computer in Windows. Which one works best depends on the relationship between the two processes. Is one process expected to start the other? In that case an out-of-process COM server would probably work best, since you can restart the other process if it is not already running.
If performance is critical, then shared memory will give you the most control the speed of passing the data between your processes.
One thing to think about is the failure semantics of running multiple processes. What does the calling process do if the callee is not there?
I have an application (A) that needs to launch another application (B). I need to pass data between the applications. I can think of two approaches. The first is to open a socket. The second is to share data via a dll.
The opening socket approach is straight forward.
The dll approach I have some questions? I can load plug-in dlls into B. I want to create a dll that A can use to pass data to B. When loading dlls, is only one instance of the dll loaded? If so, does this mean that data can be shared between applications that load the dll?
What is the better choice?
Are there other ways of doing this?
You can't effectively share data via a DLL. Other ways:
disk files
pipes
shared memory
messages
RPC
CORBA
COM
etc.
The simplest method (assuming Windows since you mention a DLL) is probably to use CreateProcess and open a pipe to the child process, as described in simplified form here: http://msdn.microsoft.com/en-us/library/ms682499.aspx
Named Pipes can be an alternative, especially if you aren't in control of the lifetime of all of the processes. http://msdn.microsoft.com/en-us/library/aa365590.aspx
For simple cases, mailslots may be a sufficient alternative.
http://msdn.microsoft.com/en-us/library/aa365574.aspx#base.using_a_mailslot_for_ipc
Here's a longer list of various Interprocess Communication techniques for Windows.
http://msdn.microsoft.com/en-us/library/aa365574.aspx
For something happening locally, using sockets seems sort of overkill. Plus you have to implement your own security mechanism to prevent spoofing attacks, rather than depending on the integrated security mechanism of most of the other IPC methods.
Its always good to explore alternative possible solutions, but I personally believe that using sockets as a transport layer for data between applications is not only future proof, but scalable as well. Using sockets will eliminate the need for you to write copious amounts of OS specific code, which could proclude you from porting your application in the future to non-Windows operating systems.
I would suggest sockets.
You can have a shared cache (example a windows service or hidden process) that can be listening - returning data to all subscribers. This using a Observer pattern approach.
I would agree somewhat with Juan Zamora M except that the service providing the data should have an API that can be requested when needed not pushed when changed via listeners.
This might help. Sharing Files and Memory
Suppose I have a daemon that is sharing it's internal state to various applications via shared memory. Processes can send IPC messages to the daemon on a named pipe to perform various operations. In this scenario, I would like to create a C++ wrapper class for clients that acts as a kind of "Remote Proxy" to hide some of the gory details (synchronization, message passing, etc) from clients and make it easier to isolate code for unit tests.
I have three questions:
Generally, is this a good idea/approach?
Do you have any tips or gotchas for synchronization in this setup, or is it enough to use a standard reader-writer mutex setup?
Are there any frameworks that I should consider?
The target in question is an embedded linux system with a 2.18 kernel, therefore there are limitations on memory and compiler features.
Herb Sutter had an article Sharing Is the Root of All Contention that I broadly agree with; if you are using a shared memory architecture, you are exposing yourself to quite a bit of potential threading problems.
A client/server model can make things drastically simpler, where clients write to the named server pipe, and the server writes back on a unique client pipe (or use sockets). It would also make unit testing simpler (since you don't have to worry about testing shared memory), could avoid mutexing, etc.
There's Boost.Interprocess library, though I can't comment on its suitability for embedded systems.