none
.NET COM Interop component does not receive data from C++ unmanaged environment RRS feed

  • Question

  • hello,

    I have a C#.NET library that has a type exposed to COM with one method. The project is maked "Register to COM Interop" and the registration is successful. In a Win32 C++ project, I import the tlb file and I want to send some data (a string) from C++ to .NET. The problem is that the string is empty on the .NET side (I was able to attach to the C++ project and view the value that .NET receives).

    [Guid("9006642B-64D0-41A9-BF98-1814A5923EA7")]
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IModelContextInterop
    {
        [return: MarshalAs(UnmanagedType.VariantBool)]
        bool AddTo([In, MarshalAs(UnmanagedType.BStr)] string name);
    }
    
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("F5FFF4EF-E66E-4B7F-83B0-B4C567C10198")]
    [ComVisible(true)]
    [ProgId("Interoperability.ModelContextInterop")]
    public class ModelContextInterop : IModelContextInterop
    {
        public bool AddTo(string name)
        {
            return true;
        }
    }

    In C++:

    #import "mscorlib.tlb" raw_interfaces_only
    #import "Interoperability.tlb" raw_interfaces_only named_guids
    using namespace Interoperability;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        CoInitialize(NULL);   //Initialize all COM Components
    
        IModelContextInteropPtr ptr;    
        auto hrModel = ptr.CreateInstance(CLSID_ModelContextInterop);
        VARIANT_BOOL b;
        hr = ptr->AddTo(BSTR("Test"),  &b);
    
        CoUninitialize();
    	return 0;
    }
    ...
    struct __declspec(uuid("9006642b-64d0-41a9-bf98-1814a5923ea7"))
    IModelContextInterop : IDispatch
    {
        //
        // Raw methods provided by interface
        //
    
          virtual HRESULT __stdcall AddTo (
            /*[in]*/ BSTR name,
            /*[out,retval]*/ VARIANT_BOOL * pRetVal ) = 0;
    };

    What am I missing?


    Eusebiu

    Wednesday, March 21, 2012 12:19 PM

Answers

  • Hello Eusebiu,

    1. Invalid BSTR Allocation.

    1.1 The way the BSTR is allocated is incorrect :

    hr = ptr->AddTo(BSTR("Test"),  &b);

    1.2 The BSTR must be allocated using SysAllocString() and later freed using SysFreeString().

    2. Solution.

    2.1 The following is a sample solution :

    BSTR bstrTest = ::SysAllocString(L"Test");
    hr = ptr->AddTo(bstrTest,  &b);
    ::SysFreeString(bstrTest);
    bstrTest = NULL;

    2.2 For more information on BSTR allocation, pls refer to :

    The Importance of Proper BSTR Allocation.

    http://limbioliong.wordpress.com/2011/08/13/the-importance-of-proper-bstr-allocation/

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    • Marked as answer by Eusebiu Thursday, March 22, 2012 3:42 PM
    Thursday, March 22, 2012 9:48 AM

All replies

  • If I put [MarshalAs(UnmanagedType.LPStr)], then the data is passed.

    Eusebiu

    Wednesday, March 21, 2012 2:55 PM
  • Hello Eusebiu,

    1. Invalid BSTR Allocation.

    1.1 The way the BSTR is allocated is incorrect :

    hr = ptr->AddTo(BSTR("Test"),  &b);

    1.2 The BSTR must be allocated using SysAllocString() and later freed using SysFreeString().

    2. Solution.

    2.1 The following is a sample solution :

    BSTR bstrTest = ::SysAllocString(L"Test");
    hr = ptr->AddTo(bstrTest,  &b);
    ::SysFreeString(bstrTest);
    bstrTest = NULL;

    2.2 For more information on BSTR allocation, pls refer to :

    The Importance of Proper BSTR Allocation.

    http://limbioliong.wordpress.com/2011/08/13/the-importance-of-proper-bstr-allocation/

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    • Marked as answer by Eusebiu Thursday, March 22, 2012 3:42 PM
    Thursday, March 22, 2012 9:48 AM
  • Hello,

    Thanks for the solution! Indeed it works. :)

    Can you tell me a place where I can find all (or most of them :) ) COM types properly allocated (e.g. DATE, BSTR)?

    Thanks again.


    Eusebiu

    Thursday, March 22, 2012 11:25 AM
  • Hello Eusebiu,

    1. >> Can you tell me a place where I can find all (or most of them :) ) COM types properly allocated (e.g. DATE, BSTR)?

    I assume you mean APIs that initialize various Variant Types. You can check out :

    Automation Functions (http://msdn.microsoft.com/en-us/library/aa913619.aspx)

    2. The DATE type (which is actually a double), for example, can be initialized using SystemTimeToVariantTime().

    3. SAFEARRAYs are initialized via various SafeArray*() APIs.

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    Thursday, March 22, 2012 2:36 PM
  • Thanks! :)

    Eusebiu

    Thursday, March 22, 2012 3:42 PM