سؤال

وأنا أعمل على مجمع PInvoke لمكتبة لا يدعم سلاسل يونيكود، ولكن لا دعم سلاسل ANSI متعددة بايت. في حين تفيد التحقيق FxCop على المكتبة، لاحظت أن التنظيم سلسلة المستخدمة لها بعض الآثار الجانبية المثيرة للاهتمام. طريقة PInvoke كان يستخدم "الأنسب" رسم الخرائط لإنشاء سلسلة ANSI بايت واحد. للتوضيح، وهذا ما بدا أسلوب واحد مثل:

[DllImport("thedll.dll", CharSet=CharSet.Ansi)]
public static extern int CreateNewResource(string resourceName);

ونتيجة استدعاء هذه الوظيفة مع سلسلة يحتوي على أحرف غير ASCII هي أن يجد ويندوز شخصية "وثيقة"، عموما هذا يبدو أنه ينتهي به الأمر "؟؟؟". إذا كان لنا أن ندعي أن "أ" هو شخصية غير ASCII، ثم يمر "القط" كمعلمة من شأنه أن يخلق مورد المسمى "ج؟ ر".

إذا كنت اتبع الإرشادات في حكم FxCop، وأنا في نهاية المطاف مع شيء من هذا القبيل:

[DllImport("thedll.dll", CharSet=CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern int CreateNewResource([MarshalAs(UnmanagedType.LPStr)] string resourceName);

وهذا يدخل تغييرا في السلوك. الآن عند حرف لا يمكن تعيين يتم طرح استثناء. هذا يقلقني لأن هذا هو تغيير فصل، لذلك أود في محاولة لحشد السلاسل كما ANSI متعددة البايت ولكن لا استطيع ان ارى وسيلة للقيام بذلك. يتم تحديد UnmanagedType.LPStr أن تكون أحادية البايت ANSI سلسلة، LPTStr will be Unicode or ANSI depending on the system, and LPWStr is not what the library expects.

وHow would I tell PInvoke to marshal the string as a multibyte string? I see there's a WideCharToMultiByte() API function, could I change the signature to expect an IntPtr إلى سلسلة I خلق في الذاكرة غير المدارة؟ يبدو مثل هذا لا يزال لديه الكثير من المشاكل التي التنفيذ الحالي له (لا يزال قد تضطر إلى إسقاط أو الشخصيات البديلة)، لذلك أنا لست متأكدا إذا كان هذا يمثل تحسنا. هل هناك طريقة أخرى من التنظيم الذي أنا في عداد المفقودين؟

هل كانت مفيدة؟

المحلول

وANSI <م> هو متعددة بايت، ويتم ترميز سلاسل ANSI وفقا لمخطط الشفرة تمكين حاليا على النظام. WideCharToMultiByte يعمل بنفس الطريقة التي P / استدعاء.

وربما ما كنت بعد هو تحويلها إلى UTF-8. وعلى الرغم من WideCharToMultiByte يدعم هذا، وأنا لا أعتقد P / استدعاء يفعل، لأنه من غير الممكن أن تعتمد UTF-8 كما الشفرة ANSI على نطاق المنظومة. في هذه المرحلة كنت أن تبحث في تمرير السلسلة بمثابة IntPtr بدلا من ذلك، ولكن إذا كنت تفعل ذلك، يمكنك استخدام فضلا الطبقة Encoding تمكنت من القيام التحويل، بدلا من WideCharToMultiByte.

نصائح أخرى

وهنا هو أفضل طريقة وجدتها لتحقيق ذلك. بدلا من حشد كسلسلة، المارشال كما بايت []. وضع المسؤولية على المتصل من API وظيفة pinvoke تحويله إلى مجموعة بايت في الأزياء الأنسب. على الأرجح باستخدام واحدة من الطبقات Text.Encoding.

إذا كنت في نهاية المطاف الحاجة إلى استدعاء WideCharToMultiByte يدويا، وأود أن نتخلص من ع / استدعاء يدويا وحشد ذلك باستخدام WideCharToMultiByte في ++ / CLI الدالة المجمع C. تمكنت C ++ هو أفضل بكثير في هذه السيناريوهات إمكانية التشغيل المتداخل من C # هو.

ورغم ذلك، إذا كان هذا هو الوحيد ص / استدعاء لديك، هو على الأرجح لا يستحق كل هذا العناء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top