C# - Call C DLL function synchronous

279 views Asked by At

I'm trying to call a dll function in C# with a paramter that is mentioned in the documentation as "...If pfn = NULL is passed, the call is synchronous. ". I'm actually passing NULL (IntPtr.Zero) to it, so the method should be called synchronous. Now I'm getting all the time a "FatalExecutionEngineError", ErrorCode 0xc0000005 when I call the method and I think that the synchronization is the problem.

So my question: How can I call a C DLL method synchronous in C#? Or do I need for that method a callback function?

The dll comes from the Siemens WinCC Runtime, the documentation about the methods are here (GetFocus Method is on page 1923): https://cache.industry.siemens.com/dl/files/216/109755216/att_940522/v1/WCC_PReference_en-US.pdf?download=true

The dll import:

[DllImport("PDLRTAPI.dll", EntryPoint = "PDLRTGetFocusW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern bool PDLRTGetFocus([In] UInt16 adrMode,
                                             [In, Out] ref FOCUSINFO pFocusInfo,
                                             [In, Out] IntPtr pfn,
                                             [In, Out] IntPtr pvUser,
                                             [In, Out] [MarshalAs(UnmanagedType.LPStruct)]
                                                       CMN_ERROR_MANCLASS pError);

The method call:

pdlrtapiDLLWrapper.FOCUSINFO focusinfo = new pdlrtapiDLLWrapper.FOCUSINFO();
            bRet = pdlrtapiDLLWrapper.PDLRTGetFocus((UInt16)1, ref focusinfo, IntPtr.Zero, IntPtr.Zero, err);

The struct of the FOCUSINFO in C#

[StructLayout(LayoutKind.Auto, CharSet = CharSet.Unicode)]
        public class FOCUSINFO
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string szPicture;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string szObject;
        }

The struct of the FOCUSINFO in the PDLRTAPI.h

typedef struct tagFOCUSINFOW
{
    WCHAR           szPicture[256];
    WCHAR           szObject[256];
} FOCUSINFOW, *LPFOCUSINFOW;

The typedef of the ADRMODE is:

typedef     unsigned short  ADRMODE;
1

There are 1 answers

0
Eicher16ps On

Update:

It turned out, that the FOCUSINFO parameter needs to be only an "out" parameter and not a "reference". So the correct code is:

[DllImport("PDLRTAPI.dll", EntryPoint = "PDLRTGetFocusW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern bool PDLRTGetFocus([In] UInt16 adrMode,
                                             [Out] FOCUSINFO pFocusInfo,
                                             [In, Out] IntPtr pfn,
                                             [In, Out] IntPtr pvUser,
                                             [In, Out] [MarshalAs(UnmanagedType.LPStruct)] CMN_ERROR_MANCLASS pError);

So to everyone who is running into this problem: Check the arguments and especially the data-types to the dll function twice...

Anyway, thanks to everyone who tried to help me.