C# 如何将PWCHAR传递给C++;来自C的dll# 我有一个用C++编写的DLL,我想从C语言调用它。函数输出输出和Dead,DaCar变量也由C++函数读取。

C# 如何将PWCHAR传递给C++;来自C的dll# 我有一个用C++编写的DLL,我想从C语言调用它。函数输出输出和Dead,DaCar变量也由C++函数读取。,c#,c++,dll,pinvoke,dllimport,C#,C++,Dll,Pinvoke,Dllimport,我试图以不同的方式从C#调用函数,但每次都遇到AccessViolationException:“试图读取或写入受保护的内存。这通常表示其他内存已损坏。” C++dll: extern "C" _declspec (dllexport) int convertVirtualKeyToWChar(int virtualKey, PWCHAR outputChar, PWCHAR deadChar); C#代码1: C#代码2: 这是暗箭伤人,所以请注意,清空 将单个元素数组传递给每个char[]

我试图以不同的方式从C#调用函数,但每次都遇到AccessViolationException:“试图读取或写入受保护的内存。这通常表示其他内存已损坏。”

C++dll:

extern "C" _declspec (dllexport) int convertVirtualKeyToWChar(int virtualKey, PWCHAR outputChar, PWCHAR deadChar);
C#代码1:

C#代码2:


这是暗箭伤人,所以请注意,清空

将单个元素数组传递给每个
char[]
参数。

尝试此操作(请记住,如果在Alloc和Free之间引发异常,将导致内存泄漏,因此在中构建一些错误处理):

注意:函数的两个
PWCHAR
参数
convertVirtualKeyToWChar
不明确。它们可以是指向单个
WCHAR
的指针,也可以是指向
WCHAR
字符串的指针。给定函数和参数的名称,此答案假定它们是指向单个
WCHAR
的指针

您要使用以下选项:

导致崩溃的原因有两个:
DllImport
默认为ANSI字符集和StdCall调用约定。您的C++ DLL没有指定任何调用约定,因此它将默认为CDecl。
请参见和

从技术上讲,CharSet用于了解封送处理程序处理字符串的方式。ref/out字符将作为wchar\u t*进行封送处理,而不考虑字符集。@peter字符集设置确实会影响单个字符的封送处理。我做了一个测试程序来验证。如果我有一个C<代码> char < /Code >,并将其值设置为<代码> \x1042 '< /Code >,C++函数将获得相同的Unicode字符集值,但是如果字符集是ANSI或未指定的,则代码< > \x3f 。我原以为马歇尔不会为一个角色费心,但它确实如此。
[DllImport("keylib.dll")]
static extern int convertVirtualKeyToWChar(int virtualKey,
               StringBuilder output,
               StringBuilder deadchar);
static extern int convertVirtualKeyToWChar(int virtualKey,
           out char output,
           ref char deadchar);
static extern int convertVirtualKeyToWChar(int virtualKey,
                                           char[] output,
                                           char[] deadchar);
 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);
[DllImport("keylib.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl)]
static extern int convertVirtualKeyToWChar( int virtualKey,
       out char output,
       ref char deadchar );