PInvoke - كيفية تمثيل حقل من واجهة COM
سؤال
أنا الرجوع COM هيكل أن يبدأ على النحو التالي:
[scriptable, uuid(ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e)]
interface nsICacheSession : nsISupports
{
/**
* Expired entries will be doomed or evicted if this attribute is set to
* true. If false, expired entries will be returned (useful for offline-
* mode and clients, such as HTTP, that can update the valid lifetime of
* cached content). This attribute defaults to true.
*/
attribute PRBool doomEntriesIfExpired;
...
لقد وجدت مدونة على استيراد تلك الواجهة في C# التطبيق.المدونة يجب أن تكون خاطئة على الرغم من ، set
الطريقة لا يبدو أن تكون مفيدة أيضا يلقي خطأ عند محاولة الاتصال فقط أن نرى ما سيحدث:
[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
[return: MarshalAs(UnmanagedType.Bool)]
void set_doomEntriesIfExpired();
[return: MarshalAs(UnmanagedType.Bool)]
bool get_doomEntriesIfExpired();
...
ما هي الطريقة الصحيحة لضبط قيمة doomEntriesIfExpired
و كيف يمكنني الإشارة هذا من الكود ؟
تحرير
لقد غيرت بلدي البرمجية التالية ، والتي أسفرت عن "النظام.AccessViolationException:محاولة قراءة أو كتابة الذاكرة المحمية يادا يادا...":
[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
void set_doomEntriesIfExpired(bool enabled);
bool get_doomEntriesIfExpired();
...
المحلول
الجواب إدراج جيدة.في Interop COM bools يتم تنظيم مثل VARIANT_BOOL بشكل افتراضي لذلك إضافة MarshalAs السمة أن أقول منظم لاستخدام معيار 4 بايت منطقي نوع هو الصحيح ، على الرغم جالبة جزء من المعادلة يحتاج السمة وأضاف أيضا.
في عام ، أنا أريد أن أترك خصائص محددة في واجهة خصائص بدلا من كسر بها في حاصل على واضعي.يطابق دلالات تعريف واجهة أفضل و عادة ما تكون أسهل في القراءة أيضا.يجب أن تكون قادرا على إعادة كتابة COM استيراد التعريف على النحو التالي الاحتفاظ السمة طبيعة doomEntriesIfExpired:
[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
bool doomEntriesIfExpired
{
[param:MarshalAs(UnmanagedType.Bool)]set;
[return:MarshalAs(UnmanagedType.Bool)]get;
}
...
نصائح أخرى
حقيقة أنك الدولة [return: MarshalAs(UnmanagedType.Bool)]
الخاص بك void set
الأسلوب الواضح أن مصدر الخطأ.
وقال أن تمكنت من التعليمات البرمجية C++ البرنامج المساعد موزيلا دون [عودة ...] به في .idl, على سبيل المثال:
[scriptable, uuid(ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e)]
interface nsICacheSession : nsISupports
{
void set_doomEntriesIfExpired(in bool value);
bool get_doomEntriesIfExpired();
}
بالمناسبة, هل أنت متأكد من أنك يمكن أن رمز nsi المساعد في C# ؟
اتضح الجواب هو التالي:
[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
void set_doomEntriesIfExpired([In, MarshalAs(UnmanagedType.Bool)] ref bool enabled);
bool get_doomEntriesIfExpired();