none
Interop Problem in C# RRS feed

  • Question

  • I'm not 100% sure this is the right place to post this, but I'll give it a try. If it should be posted in a different forum, please let me know which one and I'll take it there.

    I'm working on a C# program that will utilize a vendor-provided OCX that appears to have been written in C++. Its methods pass SAFEARRAYs as well as more usual data types. The vendor provided a tutorial showing how to use their OCX in a C++ program. I've converted this code to C# as best as I know how, but the interop stuff is throwing me for a loop (I'm new to that kind of thing).

    To offer two simple examples that use what should be straightforward data types:

                String Version = "";
                int Err;
                Err = axAud1.ACVersion(out Version);
                Err = axAud1.ACInit(1, 5, "C:\\some_directory_path", (int)this.Handle);


    Here, axAud1 is a reference to the vendor control. The ACVersion method is supposed to return a string containing the version of the control. The ACInit method passes several values used to initialize the control. Both return an integer error value.

    C# says the signatures look like this:

    int ACVersion(out string)
    int ACInit(int, int, string, int)

    The vendor's C++ tutorial has the following code to do the same thing:

    BSTR bstrVersion = NULL;

    int Err;

    Err = m_Audctrl.ACVersion(&bstrVersion);

    Err = m_Audctrl.ACInit(1,5, "c:\\some_directory_path", (OLE_HANDLE)m_hWnd);


    When I run the C# code, however, I get the error:

    "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

    I've spent a lot of time today searching for an answer to this and have come up empty-handed. The only thing I can think of is that possibly the way the OCX is implemented won't allow correct marshalling of the data. Any help anyone can offer would be appreciated, or, as I said, if this is not the correct place for this kind of question, please direct me to the correct place. Thank you!




    Tuesday, May 13, 2008 8:36 PM

All replies

  • Thank you for your posting.  I have moved this thread to the Common Language Runtime forum for visibility.  Your question will be addressed there.

    Wednesday, May 14, 2008 2:28 PM
    Moderator
  • lehket said:

    I'm not 100% sure this is the right place to post this, but I'll give it a try. If it should be posted in a different forum, please let me know which one and I'll take it there.

    I'm working on a C# program that will utilize a vendor-provided OCX that appears to have been written in C++. Its methods pass SAFEARRAYs as well as more usual data types. The vendor provided a tutorial showing how to use their OCX in a C++ program. I've converted this code to C# as best as I know how, but the interop stuff is throwing me for a loop (I'm new to that kind of thing).


    Well, I think this and either the C# or VC++ forum would be good choices.

    With regard to matching C# and C/C++ entries and calls, there are some resources, and a tool, that might help you understand how to match things up.  The resources are on the .NET interop Resources thread. (That is not a good place for your question, but the resources might be helpful.)
    http://orcmid.com/BlunderDome/clueless/
    Sunday, June 29, 2008 12:00 AM
    Moderator
  • There's evidence your OCX vendor didn't know what he was doing when he wrote the IDL for the component.  The return value type for these functions should be HRESULT, not int.  The Version argument for ACVersion should have been attributed with [out, retval].  [propget] wouldn't have hurt either.  Same with ACInit, "handle" should have been unsigned int, not int.  You're likely to get a crash on the (int) type cast.

    All and all, it is pretty likely that the IDL was so bad that it simply confused the stuffing out of Tlbimp.exe.  You would have to decompile the generated interop assembly and modify the function signatures by hand.  That's not a lot of fun and hard to get right.  The next approach is to write a managed class wrapper in the C++/CLI syntax so you get a managed interface in C# but can use C++ to call the vendor's interface methods.  Be sure to get exception handling right, throw when the return value is negative.

    Last but not least, call the vendor and complain.  You're not likely to be the only one with this problem.  
    Hans Passant.
    Sunday, June 29, 2008 12:50 PM
    Moderator