none
C# interop DLL method seems to return wrong values RRS feed

  • Question

  • My C# method returns a bool value. In this particular test I know it was returning true.

    But the interface version of the method has the bool return value as a VARIANT_BOOL reference argument.

    When I make the call:

    VARIANT_BOOL bResult;
    pInterface->SomeFunction(&bResult);
    if(bResult == VARIANT_FALSE)
      bSomeError = true;
    


    I am finding that sometimes my MFC C++ calling code receives what it considers to be a VARIANT_TRUE response but at other times it considers it to be a VARIANT_FALSE response, even though I know that the method itself had returned "true" by the use of a message box popup.

    So this is making my application raise errors to the user when technically there wasn't any.

    Please advise as to what I can do to resolve this issue and make my application / interop COM DLL relationship more stable.

    Thank you in advance.

    Andrew

    PS. I was not sure which forum to use.

    Tuesday, October 25, 2011 5:11 AM

Answers

  • Hello Andrew,

     

    1. >> But that got converted into a VARIANT_BOOL retval parameter in the TLH file.

    1.1 The .NET bool type is always marshaled as VARIANT_BOOL when exposed to COM.

     

    2. >> Why did the bool retval go bogus on me?

    2.1 I assume that the ProcessBatchEvents() was previously defined as follows :

    void ProcessBatchEvents(ref bool iResult);
    
    


    2.2 It is possible that the "iResult" parameter got assigned by the COM-Callable-Wrapper to a default value if inside ProcessBatchEvents(), "iResult" remained unassigned when the function returned. A "ref" parameter need not be assigned by the function before it returns.

    2.3 To ensure that this does not happen, what you can do is to change the parameter from being a "ref" parameter to an "out" parameter :

    public void ProcessBatchEvents(out bool iResult);
    

    In this situation, the C# compiler will ensure that ProcessBatchEvents() will assign a value to "iResult" before the function returns.

     

    - Bio.

     


    Please visit my blog : http://limbioliong.wordpress.com/
    • Marked as answer by Paul Zhou Tuesday, November 1, 2011 7:03 AM
    Tuesday, October 25, 2011 10:47 AM
  • Hi

    Thanks for the clarification about "out".I was using:

     

    public bool ProcessBatctEvents()

     

    initially. I tried changing it to the "out bool" approach for all my methods and I found I started getting the same error again when testing against VARIANT_FALSE.

     

    So I have altered all my methods to use "out Int64 iResult" and in C++ I pass a __int64 variable. This at the moment seems stable.

    Andrew


    • Edited by ajtruckle Tuesday, October 25, 2011 12:18 PM
    • Marked as answer by Paul Zhou Tuesday, November 1, 2011 7:03 AM
    Tuesday, October 25, 2011 12:18 PM

All replies

  • Showl the C# code.  Your C++ code snippet seems OK, as long as your C# code always returns a value.
    Jose R. MCP
    Tuesday, October 25, 2011 6:35 AM
  • I changed the code thus:

     

    Calling code:
    
                                        if (bProcessBatch)
                                        {
                                            long iResult;
                                            pInterface->ProcessBatchEvents(&iResult);
                                            if (iResult == FALSE)
                                                bResult = false;
                                        }
    
    C# declaration:

     void ProcessBatchEvents(ref int iResult);
    C# definition:

     public void ProcessBatchEvents(ref int iResult) { bool bResult = true; try { EventFeed batchResultFeed = (EventFeed)m_Service.Batch(m_BatchFeed, new Uri(m_Feed.Batch)); //check the return values of the batch operations to make sure they all worked. //the insert operation should return a 201 and the rest should return 200 bResult = true; foreach (EventEntry entry in batchResultFeed.Entries) { if (entry.BatchData.Status.Code != 200 && entry.BatchData.Status.Code != 201) { bResult = false; } } m_BatchFeed = null; } catch (LoggedException /*ex*/) { /*MessageBox.Show(ex.Message.ToString(), "ProcessBatchEvents", MessageBoxButtons.OK, MessageBoxIcon.Error);*/ bResult = false; } //return bResult; if (bResult) iResult = 1; else iResult = 0; //return true; }


    Previously it was just returning a bool. And all paths returned a bool. But that got converted into a VARIANT_BOOL retval parameter in the TLH file.

    I changed the logic as above and now I do not get any false errors. It correctly fills my variable with the right value.

    That seems to work every time. I am not getting an error now.

    My concerns are:

    1. Why did the bool retval go bogus on me?
    2. Do I have to change all my methods to pass a int by ref for a result to be safe?

    Andrew

    Tuesday, October 25, 2011 8:15 AM
  • Hello Andrew,

     

    1. >> But that got converted into a VARIANT_BOOL retval parameter in the TLH file.

    1.1 The .NET bool type is always marshaled as VARIANT_BOOL when exposed to COM.

     

    2. >> Why did the bool retval go bogus on me?

    2.1 I assume that the ProcessBatchEvents() was previously defined as follows :

    void ProcessBatchEvents(ref bool iResult);
    
    


    2.2 It is possible that the "iResult" parameter got assigned by the COM-Callable-Wrapper to a default value if inside ProcessBatchEvents(), "iResult" remained unassigned when the function returned. A "ref" parameter need not be assigned by the function before it returns.

    2.3 To ensure that this does not happen, what you can do is to change the parameter from being a "ref" parameter to an "out" parameter :

    public void ProcessBatchEvents(out bool iResult);
    

    In this situation, the C# compiler will ensure that ProcessBatchEvents() will assign a value to "iResult" before the function returns.

     

    - Bio.

     


    Please visit my blog : http://limbioliong.wordpress.com/
    • Marked as answer by Paul Zhou Tuesday, November 1, 2011 7:03 AM
    Tuesday, October 25, 2011 10:47 AM
  • Hi

    Thanks for the clarification about "out".I was using:

     

    public bool ProcessBatctEvents()

     

    initially. I tried changing it to the "out bool" approach for all my methods and I found I started getting the same error again when testing against VARIANT_FALSE.

     

    So I have altered all my methods to use "out Int64 iResult" and in C++ I pass a __int64 variable. This at the moment seems stable.

    Andrew


    • Edited by ajtruckle Tuesday, October 25, 2011 12:18 PM
    • Marked as answer by Paul Zhou Tuesday, November 1, 2011 7:03 AM
    Tuesday, October 25, 2011 12:18 PM