COM Interop Question

I have a VC6 ATL COM Object that accepts a BSTR as an input parameter in one of it's methods. The COM Object expects an ascii buffer to be embedded in the body of this BSTR and uses a call to SysStringByteLen to dynamically create an appropriately sized single byte char array for holding the extracted contents based on the results obtained from interrogating the size prefix of the BSTR. The COM interop wrapper generated from this dll defines this parameter as a System.String that gets marshalled as UnmanagedType.BStr. I am trying to use this method from managed code (C#) but am having difficulty creating an ascii encoded string parameter from my binary data (a byte array). Is there anyway to do this in such a fashion that I can pass binary data embedded in a managed string and include the appropriate BSTR allocation size prefix What flavor of Encoder.GetString call should I be using, or is that the wrong approach entirely

Thanks in advance




Answer this question

COM Interop Question

  • Adam.Kahtava

    Hi Mike,

    I am glad that you have found the solution.

    If you still have any concern, please feel free to post here.

    Best regards,
    Peter Huang



  • Pankaj11

    Thanks for the Tip Peter but modifying the COM object is not an option.

    "Back in the day" it was pretty common to marshal custom data structures as embedded binary content in the body of a BSTR. Such BSTRs were created by using a call to SysAllocStringByteLen(char FAR*, UINT) - see http://msdn.microsoft.com/library/default.asp url=/library/en-us/wcedcom/html/cerefsysallocstringbytelen.asp for the docs.

    On the receiving end a COM object could then apply a little memcpy magic to extract the binary contents to "rehydrate" the binary data into the desired data structure.

    i.e.

    STDMETHODIMP FooBar::ExtractAsciiFromBSTR(BSTR bstrMessage)
    {
    long len = SysStringByteLen(pbstrMessage);
    char *psz = new char[len];
    memcpy(psz, pbstrMessage, len);

    //Can now do something interesting with contents...
    //The char* used here could have just as easily been a pointer to a structure
    //i.e. memcpy(pStruct, bstrMessage, sizeof(Struct));

    }

    BTW - my earlier isuue has been resolved by modifying the interop logic to marshall the parameter using MarshalAs(UnmanagedType.AnsiBStr).

    Thanks again.



  • Bernd Wechner

    Hi ,

    You may take a look at the link below.

    <quote>
    L, LPOLESTR, LPWSTR, BSTR, and CComBSTR
    L creates hard-coded UNICODE strings, e.g., L"Foo"
    LPOLESTR is a null-terminated UNICODE string
    LPOLESTR is a LPWSTR which is a WCHAR *
    BSTR and LPOLESTR are not identical
    BSTRs are also null-terminated UNICODE strings, but the beginning of the string contains its length
    BSTRs are the "preferred string" of COM, so all new interfaces should use BSTR and not LPOLESTR
    CComBSTR is a convenient wrapper class around BSTR - #include <atlbase.h> to get it
    </quote>

    COM Strings
    http://www.devguy.com/fp/Tips/COM/bstr.htm

    NOTE: BSTRs are also null-terminated UNICODE strings, but the beginning of the string contains its length. So I just wonder why you wrap ascii in BSTR So far we use Unicode for most application as possible.

    If you still have any concern, can you post the sample ATL method that take a BSTR parameter and handle ascii character
    Because as the link above, we have speical ways to convert BSTR to ascii althought commonly we suggest use unicode all the time.

    Best regards,
    Peter Huang



  • COM Interop Question