استدعاء وظيفة C++ dll من C#:من الهياكل والسلاسل ومصفوفات wchar_t
-
22-08-2019 - |
سؤال
إليك مشكلة بسيطة أريد حلها، لكنها تجعلني أشعر أن شعري تحول إلى اللون الرمادي حيث أن كل محاولاتي ترجع لي نفس الخطأ:
""تمت محاولة قراءة أو كتابة الذاكرة المحمية.وهذا غالباً ما يكون مؤشراً على أن الذاكرة الأخرى تالفة."
لدي تطبيق نموذجي مكتوب بلغة 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 بشكل صحيح، لأن هذه البنية هي التي تتم كتابتها بواسطة الدالة converterHKID_Name.ولكن كيف يجب أن أصلحه؟
المحلول
أعتقد أنه يجب أن يعمل إذا كنت
- تغيير الإعلان على
convertHKID_Name
لCharSet.Ansi
- قم بإزالة "المرجع" من معلمة السلسلة
- مرر ال
string num
مباشرة الىconvertHKID_Name
بدلا من الاتصالWideCharToMultiByte
نصائح أخرى
وكتبت على مجمع المدارة في C ++ لبلدي دلل غير المدارة، ولكن حصلت على تمسك قليلا مرة أخرى.
وتابع هنا
لا تنتمي إلى StackOverflow