Share asio::io_context with dll? - c++

I have an application that imitates state of a vehicle and uses various plugins to transmit data. Each plugin is loaded dynamically and provides protocol-specific implementation for an interface to send the data. By specification each plugin may be operating concurrently and a sending method may be asynchronous.
I would like to be able to share asio::io_context or asio::thread_pool to utilize those resources allocated by the application (core). Each plugin would use asio::strand if needed. I really wouldn't want plugins to spawn new threads.
To provide compiler independence the API for a plugin is in C, hence I can't pass asio entities just like that.
Is it possible though to expose a context or a thread pool to a dynamically loaded dll which may be compiled with another toolchain?
Maybe via some kind of native handles?
Maybe I could wrap a custom executor?
I didn't find any constructors in the reference which would use native handles, etc.

Related

Where do I need to call CoInitialize in the C++ REST SDK?

I need to call some COM APIs from a simple REST server using the REST SDK. It's similar to the BlackJack sample code.
Whenever I try to create a COM object I get an exception that CoInitialize has not been called. But where exactly can I initialize the thread that processes the REST request? I couldn't find any documentation.
I tried the constructor (BlackJackDealer in the sample) but that does not work:
BlackJackDealer::BlackJackDealer(utility::string_t url) : m_listener(url)
{
CoInitialize(0);
...
}
Tasks in the C++ REST SDK execute on the Windows Threadpool by default. Instead of trying to join threadpool threads to an STA (which should be considered an anti-pattern), you can either:
Specify a custom scheduler (deriving from pplx::scheduler_interface) when creating tasks that need to call COM methods. See pplxinterface.h for the interface declaration and windows_scheduler::schedule() inside pplxwin.cpp for how the default scheduler is implemented on various Windows flavors.
Manually marshall any COM interactions to a thread that you own and control (and have called CoInitialize on). This probably means something like having a global vector of std::function objects that you protect with the usual mutex/condition_variable dance.
You may need to perform manual marshalling even if you go the custom scheduler route, but the custom scheduler will interoperate better with the existing task-based APIs.

How MSXML works ? (How in-process COM object works)

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.

How to provide a function for the other program to call it?

Assume I use a C++ program to maintain a queue in Linux, and do some things with the data in the queue, and now I want to run it in the background and provide a function, therefore other programs could simply call it to pull a data into my queue.
What's the best way to do this?
If your programs are running as two separate processes, You cannot just call functions in other process directly, you will need a Interprocess communication Mechanism(IPC) to communicate between the two processes.
Usually, this is done as follows:
The process which you want to communicate to provides a client side library, The process or application which wants to communicate with the process links to this client side library. This client side library provides simple function calls which your calling process/application can call directly. The client side library implements the necessary IPC mechanism to communicate with the remote process.
What I understand is that you want a client API that wraps communication with the queue.
You need to create a separate library that contains and exports the API, and include it in the programs that want to use it.
class Communicator
{
public:
bool putData(Data* data);
bool getData(Data*& data);
};
The implementation of Communicator does the actual communication with the queue via IPC, but you abstract that layer out.
There are a variety of mechanisms to do this, from creating your own server, using IPC, RPC, CORBA to name a few.
As to the best it depends on a variety of factors.
In the OP you mentioned you want a queue with one process processing it - perhaps using shared memory and a mutex would be a simple solution, with a library to access the queue for both processes.

Accessing the C++ COM dll from Webservice

I am using a COM dll from a web service.
The COM dll is added as reference. And I am declaring the object as static in Global.asax.
I am creating the COM object in the Application_Start.
I have to call the COM dll interface function in each request.
I am getting exceptions here as memory corruption.I could see the logs that it happens when simultaneous requests come up.
Please let me know what is the best way to do that. How to make it thread safe.?
Try creating a new instance in each request and not use application scope for the object.
If you are accessing it at application scope(eg through Application_Start) you will need to make sure it is safe for multithreading. I don't know how C++ dlls handle threading but you might be able to manage multithreading at the asp.net level.
For example To manage a simple application level counter the code is something like:
Application.Lock();
Application["SomeGlobalCounter"] =
(int)Application["SomeGlobalCounter"] + 1;
Application.UnLock();
For more information you might want to see the MSDN page on Application State.
If the COM object is apartment threaded, COM provides the synchronization to enforce a single execution of a method per thread.
Generally, though, COM should be complaining of multiple threads trying to access an instance of an object using the same pointer shared across threads. Having a static variable holding a pointer to the object is probably a bad idea.
Once the COM object shared library is loaded somewhere (in-proc or out-of-proc) by creating an instance, creation of additional instances per thread should be fairly quick. That is, of course, dependent on what types of things that are being done during object construction.

Can an out-of-process COM object determine its parent process?

From an out-of-process COM object (LocalServer32) can I determine the client process that requested the creation of the object? - to be specific I need to get hold of the client processes command line.
This question arrises because (due to poor standardisation, implementation and support) the potential 3rd party clients of the object have a variety of idiosyncracies which the object needs to workaround.
To do this the object needs to be able to identify its current client.
Extending the interface of the COM object so that the client can identify itself is unfortunately not possible ... or to be more precise the interface can be extended but I won't be able to get the clients to call the extension.
Having looked into this further I suspect the answer is going to be "NO", but by all means tell me I'm wrong.
Using Process Explorer I can see that the parent process for my COM object is an instance of "svchost.exe", and not the client application.
Because COM server processes are shared by all clients of the same AppID, it's not possible to actually get the PID of the client application. As #Anders said, you can use CoImpersonateClient (or, better, call CoGetCallContext and interrogate the resulting IServerSecurity) to find the account and login session of the caller, but you cannot get the process itself.
If you are trying to work around bugs in legacy clients, I would recommend you create a new set of CLSIDs (or IIDs, if you can emulate all the bugs the legacy clients rely on with shims) for new (non-legacy) clients with VERY strict input validation, and implement new features only in these new CLSIDs. Legacy clients stick with their older CLSID, in which you can simply use the existing, legacy implementation (or a bug-for-bug compatible clone).
Maybe CoImpersonateClient()