3

I have the following C++ function (belongs to a COM interface, derived from IUnknown), which I want to call from C# code:

C++ declaration as documented:

HRESULT Function1([in] STRUCT1 *s1, [in, out] STRUCT2 *s2, [in] SIZE_T var1);

Declaration inside a working C++ program:

    STDMETHOD(Function1)(
    THIS_
    __out STRUCT1 * s1,
    __in_ecount_opt(var1) const STRUCT2 * s2,
    SIZE_T var1
    ) PURE;

In C# territory I define the following:

[StructLayout(LayoutKind.Sequential)]
public struct STRUCT1
{
    public uint  member1;     //HRESULT member1
    public ulong member2;     //SIZE_T member2
}

[StructLayout(LayoutKind.Sequential)]
public struct STRUCT2 
{
    public IntPtr  member1;   //VOID *member1;
    public ulong   member2;   //SIZE_T  member2;
    public STRUCT3 member3;   //STRUCT3 member3;
}

[StructLayout(LayoutKind.Sequential)]
public struct STRUCT3
{
    public int member1;  //int member1
}

I implement this function in C# as follows :

[ComImport, ComVisible(false), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("…")]
public interface Iinterface1 
{
……


    uint Function1(ref STRUCT1 s1, ref STRUCT2 s2, ulong var1);
……
}

and I invoke the function like this:

            STRUCT1 temp1 = new STRUCT1();
            temp1.member1 = 0;
            temp1.member2 = 0;

            STRUCT2 temp2 = new STRUCT2();
            STRUCT3 temp3 = new STRUCT3();
            temp3.member1 = 0;
            temp2.member1 = IntPtr.Zero;
            temp2.member2 = 0;
            temp2.member3 = temp3;
            ulong var1 = 1;

            res1 = COMobject.Function1(ref temp1, ref temp2, var1);

When function is executed I get an Access Violation Exception :

“An unhandled exception of type 'System.AccessViolationException' occurred in prog1.exe Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. “

I implemented most of functions of the same interface with no problems, as well as a lot of other interfaces in this application. This one really puzzles me.

I would really appreciate your help on this..

Thank you in advance.

5
  • You may have a look at manski.net/2012/06/pinvoke-tutorial-pinning-part-4 Commented Jan 11, 2016 at 20:31
  • You should use IntPtr for SIZE_T (only necessary if it might run on a 32 bit processor, but good practice anyway). I would also suggest you double check if the AccessViolationException is happening in the marshaling code or from within the com method itself. Commented Jan 11, 2016 at 21:08
  • @Brian : Thank you for your suggestions. Can you suggest the best way to double check if this is happening in marshalling process or within the com method? I am targetting only 64bit and source code of com method is not available. Commented Jan 13, 2016 at 8:11
  • Use a mixed mode debugger and put a break point just inside the native COM method (this is, of course, much easier if you have the source code for the com object). If you reach the break-point then the issue is probably not with the inward marshaling, If you can step through to the end of the method then the problem is probably in the outward marshaling. You might also get lucky if you break on "Access Violation" (Visual Studio groups it under "Win32 Exceptions") and check the stack trace. Commented Jan 13, 2016 at 8:37
  • Thanks Brian and Dieter for your helpfull suggestions. Finally I disassembled the .dll and found the problem in STRUCT3 member1 described above. It should be 64bit long as it holds a memory address and I work in 64bits only. Thanks again for your time helping me. Commented Jan 13, 2016 at 23:32

1 Answer 1

1

COM-Interop has a rather strange set of rules, you have to really be "into it" to reason about it. Many things can go wrong "silently" and you just have to figure it out the hard way. In similar situations, here's what I'd do to try to figure things out:

  1. Try to use the COM interface from PowerShell. It gives a nice "second POV" to see if the problem may be in your C# code. Also, it's usually much easier to do testing this way, pushing various data in.

  2. Do some debugging. Use the MessageBox() trick to halt the execution of C++ code at the start of the C++ (member) function, then attach the debugger and see what's going on.

  3. The previous point can be time consuming, sometimes a bunch of printfs of the parameters and other state can help you figure out what's going on. Combined with PowerShell, you can have a lot of inputs and see which cause issues and what kind of issues.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Srdjan for your helpfull suggestions. Finally I disassembled the .dll and found the problem in STRUCT3 member1 described above. It should be 64bit long as it holds a memory address and I work in 64bits only. Thanks again for your time helping me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.