First, I want to thank Matt Davis for this post. I know the post was not chosen as the answer to that specific question, but the post was extremely helpful to me. I had a couple small issues to fix (mostly adjusting the filepaths in the code he provided), but I was easily able to create an unmanaged C++ client for a C# WCF service using his C++ bridge method.
I am now exploring how to improve on the basic concepts presented there. Here is a bit of code from the HelloServiceClientBridge.cpp file in Matt's post:
String^ message = client->SayHello(gcnew String(name));
client->Close();
IntPtr ptr = Marshal::StringToHGlobalAnsi(message);
rv = std::string(reinterpret_cast<char *>(static_cast<void *>(ptr)));
It seems like a lot of copies of a string are going to be created here. Here are all of the potential places I see where a copy of the string may be made:
- The original unmanaged copy of the string in the
name
variable - A managed copy of the string when
gcnew String(name)
is invoked - I'm not sure, but another copy might be created when the managed string is passed as a parameter to the
SayHello()
method - The string is copied into the WCF message which is sent to the C# service
- I'm not sure, but another copy might be created by the C# service when it receives the message
- I think another copy of the string is created when
String.Format
is called - The new "Hello" string is copied into the WCF message which is sent to the client
- I'm not sure, but another copy might be created by the C# client when it receives the message
- I'm not sure, but another copy might be created when the C# client returns the string to the C++ bridge
- An unmanaged copy of the new string is created when
Marshal::StringToHGlobalAnsi(message)
is invoked - I'm not sure, but another copy might be created when the string is converted to a
std::string
Now, I realize that some copying is unavoidable when we're working with unmanaged and managed interop and interprocess communication, but I'm wondering if some this copying could be avoided. It isn't a big deal for a simple HelloWorld type example, but the cost of copying from unmanaged to managed and then again from one process to another process could be significant if a large amount of data was being passed. So, I'm wondering if there is a way to do the marshalling from unmanaged to managed and/or vice versa at the same time that the interprocess communication is happening.
One possiblity I considered was modifying the code so that the string could be copied from the unmanaged string directly into the WCF message formatted as a managed string. I thought since we have to make a copy at that point anyways, it would be nice if that copy also served the function of one of the earlier copies so we can kill two birds with one stone.
Another possibility I considered was passing an unmanaged pointer from the C++ process to the C# service through the WCF message which could then be marshalled to a managed string by the C# service. Of course, this has potential to be pretty messy figuring out who is responsible for allocating the memory and deallocating the memory for that pointer, but the copying would be reduced and the WCF message size could be significantly reduced.
Thanks for any ideas you may have!