mercredi 24 août 2016

InterComponent Interface Design in VC++

I'm designing an application with the following characteristics:

  • It is consisted of an executable and multiple DLLs.
  • The DLLs are loaded at runtime.
  • All elements (DLLs + executable) have a profile that holds the element's name + its version. It makes them addressable in the system.
  • All DLLs and the executable implement the same interface to communicate with each other:

    • virtual int query( Profile sender, Json request, std::unique_ptr<std::map<std::string, std::vector<unsigned char>>> input, std::map<std::string, std::vector<unsigned char>> * output = nullptr ) = 0;

About the Interface

Sender
represents the profile of the sender. If DLL named A decides to pass a message to DLL named B it sends its profile as the sender when calling the query function of the DLL B.

request
I decided to use JSON to exchange messages. request holds the sent message.

input
input points to a map that holds the necessary arguments for the actions included in request to be performed. I used unique_ptr to clearly enforce sink; So that the callee won't worry about inputs being modified in the caller while it is operating on them; it also lets the caller to pass nullptr in case of no input arguments to pass.

output
The caller must allocate a map then pass its pointer as output so that the callee fill it with data.

Of course in all of the above I check the given parameters. For example if output was passed nullptr I won't insert data to it.
There is a potential danger in the scenario that caller terminates before callee finishes its job.

Question 1

Can you suggest a better interface?
Please consider memory duplication and efficiency.

Question 2

I have to use /MT option when compiling using VC++. So that the executable won't require an installation of C++ runtime on the target machine. But It makes the design difficult as the memory allocated in one DLL can't be freed in another DLL. Or better explained by dxiv:

Address space is per-process, and DLLs always share the same address space with the process that loaded them, and with other DLLs loaded by the same process. It is perfectly safe to access memory allocated in one DLL function from anywhere else within the same process. What does not work with /MT is allocating memory (new) in code in one DLL, then freeing it (delete) in code from another DLL, because with /MT each DLL has its own copy of the CRT statically linked.

Hence, what changes or mechanisms do you suggest to overcome this limitation?
I have thought of a solution involves calling some functions to allocated and deallocated memory in a different DLL. Let's say A asks (sends a message to) B to perform an action and we are in B, if A provides B a function named malloc_in_A so that B can allocate memory in A, it gets easy for A to free the memory allocated by B without troubles.
But I don't think this is the best solution.
I'm open to any ideas.

Thank you

Aucun commentaire:

Enregistrer un commentaire