0

Good Day fellow developers

I have been searching the internet for 2 days now on how to do what I need and I have tried a lot of samples with no success. However, that does not mean I covered all sites - I am thinking I am blind in one eye and cannot see out the other.

At any rate, I was handed a single sheet of paper with a COM Automation Interface definition on it and was asked to develop a C# application to utilize the interface and the callbacks accordingly.

So, starting simple (or so I thought) - the C++ method signature is:

STDMETHODIMP CSimpleChatServer::CallMe(BSTR clientName, BSTR** returnMessage)

and the interface signature is:

HRESULT _stdcall CallMe([in] BSTR clientName, [in] BSTR** helloMessage);

And I need to call this from C# - I have established the Interface for ISimpleChatServer; hence, the code call I am trying is like.

string rtrnMsg = string.Empty; ImySimpleCom.CallMe("Robert", rtrnMsg)

Since the signature is an [in], I am getting an exception on trying to access protected memory.

Now, I believe it wants an IntPtr as the second parameter; however, all my attempts to get that to be taken have failed.

Please keep in mind that I am not able to change the library - it is an "As Is" legacy interface that we need to utilize for a little while longer and the provider has nobody to update it accordingly (in fact I think they do not have anyone to work on it).

Any help would be kindly welcomed.

Kind Regards, Robert S.

  • How are you creating the code for `ImySimpleCom`? Are you using p/invoke or are you using the built in COM features of .NET? – Scott Chamberlain Nov 03 '16 at 15:02
  • `SimpleCOMLib.SimpleChatServer mySimpleCom = new SimpleCOMLib.SimpleChatServer(); SimpleCOMLib.ISimpleChatServer ImySimpleCom = (SimpleCOMLib.ISimpleChatServer)mySimpleCom;` – Robert Springer Nov 03 '16 at 15:05
  • I did not mean how are you creating a new instance, I ment how are you generating the code itself for the class. I updated my previous comment but you likely needed to refresh. – Scott Chamberlain Nov 03 '16 at 15:07
  • your description of the CallMe function contains two [in] but you say you want to return helloMessage... in that case declare it [out,retval] and just take the return value. – AndersK Nov 03 '16 at 15:09
  • I apologize - I guess, maybe I am not understanding (I do appreciate your attention), I am using VS2012 and essentially using the built in templates for C#. In this instance I created a test Form application, I used a class template and then I added the code above. The form has a simple "Do It All" button that fires the instantiation of the class and hence the subsequence lines as seen below. The form has a textbox to simply display the result. – Robert Springer Nov 03 '16 at 15:12
  • The signature for the C++ function is something I am not able to change. It has a `BSTR**` as the type for the second parameter and that generated the [in] for the interface. – Robert Springer Nov 03 '16 at 15:14
  • "that generated the [in]" is strangely backwards. You **first** write the IDL, [out,retval] required. Then it is compiled by MIDL and you get a .h file that you #include in your C++ code. – Hans Passant Nov 03 '16 at 15:21

2 Answers2

1

In the .idl the interface should be

HRESULT _stdcall CallMe([in] BSTR clientName, 
                        [out,retval] BSTR** helloMessage);

So just take the return value from CallMe

SimpleChatServer mySimpleCom = new SimpleChatServer();   
string helloMessage = mySimpleCom( clientName );

When you return the string in C++/C method you allocate using SysAllocString and return that to caller by assigning to helloMessage.

i.e.

*helloMessage = SysAllocString(L"MyString");

All the above assumes that you have referenced the COM server in your C# project.

I read your question more carefully now, so you cannot change the "legacy" code? if it says

HRESULT _stdcall CallMe([in] BSTR clientName, 
                        [in] BSTR** helloMessage);

Then it should be changed because that is not correct.

AndersK
  • 35,813
  • 6
  • 60
  • 86
  • HEHE - That is what I figured and I communicated that to them, there response was "it is what it is". Ok, so technically - and as I thought, in order for me to get to whatever they are trying to pass back in that second parameter they need to correct something so that it has the `[out, retval]` parameter attribute. – Robert Springer Nov 03 '16 at 15:24
  • @RobertSpringer at the very least you will probably get a memory leak when you call the function if it remains as `[in][in]` – AndersK Nov 03 '16 at 15:33
0

Thanks All and Andres

I finally got in touch with the client and yes, the information they provided was incorrect and the [in] attribute was supposed to be [out,retval] to allow for the passing back of the string - once they corrected that, all went fine.

Great appreciation to all - Thank You