How to pass PWCHAR to C++ dll from C#
I have an dll written in C++, and I want to call it from C#. The function outputs outputChar and deadChar, the deadChar variable is also read by the C++ function.
I tried to call function from C# in different ways, but all time I got AccessViolationException: "Attempted to read or write protected memory. This is often an indication that ot开发者_运维知识库her memory is corrupt."
C++ dll:
extern "C" _declspec (dllexport) int convertVirtualKeyToWChar(int virtualKey, PWCHAR outputChar, PWCHAR deadChar);
C# code 1:
[DllImport("keylib.dll")]
static extern int convertVirtualKeyToWChar(int virtualKey,
               StringBuilder output,
               StringBuilder deadchar);
C# code 2:
static extern int convertVirtualKeyToWChar(int virtualKey,
           out char output,
           ref char deadchar);
Note:  The two PWCHAR arguments to your function convertVirtualKeyToWChar are ambiguous.  They could be pointers to a single WCHAR or pointers to aWCHAR string.  Given the name of the function and arguments, this answer assumes they are pointers to a single WCHAR.
You want to use the following:
[DllImport("keylib.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl)] static extern int convertVirtualKeyToWChar( int virtualKey, out char output, ref char deadchar );
Your crash is caused by two reasons:  DllImport defaults to the ANSI character set and StdCall calling convention.  Your C++ DLL does not specify any calling convention, so it will default to CDecl.
See DllImportAttribute.CallingConvention and DllImportAttribute.CharSet
This is a stab in the dark, so caveat emptor...
static extern int convertVirtualKeyToWChar(int virtualKey,
                                           char[] output,
                                           char[] deadchar);
Pass a single-element array to each char[] parameter.
Try this (bearing in mind that if an exception is thrown between Alloc and Free you will leak memory, so build some error handling in):
 static void Main(string[] args)
    {
        IntPtr pout = Marshal.AllocHGlobal(2);
        IntPtr pdead = Marshal.AllocHGlobal(2);
        int ret = convertVirtualKeyToWChar(1, pout, pdead);
        char output = (char)Marshal.ReadInt16(pout);
        char dead = (char)Marshal.ReadInt16(pdead);
        Marshal.FreeHGlobal(pout);
        Marshal.FreeHGlobal(pdead);
    }
    static extern int convertVirtualKeyToWChar(int virtualKey,
       IntPtr output,
       IntPtr deadchar);
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论