从C#调用C ++ dll函数:结构,字符串和wchar_t数组

时间:2009-03-25 02:55:17

标签: c# c++ struct marshalling dllimport

这是一个我需要解决的简单问题,但它让我觉得我的头发变灰了,因为我所有的尝试都给我带来了同样的错误:

“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”

我有一个用C ++编写的示例应用程序,它调用了dll。以下是相关代码:

    //function I need to call
bool convertHKID_Name(char *code,RECO_DATA *o_data);    //hkid 

//struct definition
struct RECO_DATA{
    wchar_t FirstName[200];
    wchar_t Surname[200];
};

//how it is used in C++ code
CString code;
RECO_DATA data;
GetDlgItemText(IDC_CODE,code);
char _code[200];
WideCharToMultiByte(CP_UTF8, 0, code, -1, (char *)_code, 200, NULL, NULL);
ocr->convertHKID_Name(_code,&data)

现在,当我调试C ++代码时,它做了正确的事情 - 将一些Unicode数据写入数据结构。

我试图在C#

中做同样的事情
    //my C# wrapper class
public class cnOCRsdk
{
    [StructLayout(LayoutKind.Sequential, Size=400, CharSet=CharSet.Unicode), Serializable]
    public struct RECO_DATA
    {
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 200)]
        public string FirstName;
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 200)]
        public string Surname;
    };

    [DllImport(@"cnOCRsdk.dll", CharSet=CharSet.Auto, EntryPoint = "?convertHKID_Name@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z")]
    public static extern bool convertHKID_Name(ref string num, ref RECO_DATA o_data);

    [DllImport("Kernel32.dll")]
    public static extern int WideCharToMultiByte(uint CodePage, uint dwFlags,
        [In, MarshalAs(UnmanagedType.LPWStr)]string lpWideCharStr,
        int cchWideChar,
        [Out, MarshalAs(UnmanagedType.LPStr)]StringBuilder lpMultiByteStr,
        int cbMultiByte,
        IntPtr lpDefaultChar, // Defined as IntPtr because in most cases is better to pass
        IntPtr lpUsedDefaultChar // NULL
        );
}

//my attempt to call the function from the dll
cnOCRsdk.RECO_DATA recoData = new cnOCRsdk.RECO_DATA();
string num = "262125355174";
StringBuilder sb = new StringBuilder(200, 200);
cnOCRsdk.WideCharToMultiByte(65001, 0, num, -1, sb, 200, IntPtr.Zero, IntPtr.Zero);
string sbTostring = sb.ToString();
//the next line generates the 'Attempted to read or write protected memory' error
bool res = cnOCRsdk.convertHKID_Name(ref sbTostring, out recoData);

我的猜测是我没有正确编组RECO_DATA结构,因为它是由convertHKID_Name函数写入的结构。但我该如何解决呢?

2 个答案:

答案 0 :(得分:2)

我认为如果你

它应该有用
  1. 更改声明 convertHKID_NameCharSet.Ansi
  2. 从字符串中删除“ref” 参数
  3. 通过string num 直接转到convertHKID_Name 打电话给WideCharToMultiByte

答案 1 :(得分:0)

我在C ++中为我的非托管dll编写了一个托管包装器,但是再次卡住了。

接下来

Passing C# data type parameters to dll written in C++?