开发者

How to pass PWCHAR to C++ dll from C#

开发者 https://www.devze.com 2023-02-21 21:20 出处:网络
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 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);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号