سؤال

ما هو الفرق بين وظيفة عضو ثابت ووظيفة الارتباط خارجي "C"؟ على سبيل المثال، عند استخدام "MakeContext" في C ++، أحتاج إلى تمرير مؤشر للعمل. توصي Google باستخدام الارتباط الخارجي "C" بالنسبة لذلك، لأن "MakeContext" هو C. لكنني اكتشفت أن استخدام الأعمال الثابتة أيضا. هل أنا محظوظ فقط أو ...

class X {
   public:
   static void proxy(int i) {}
}
makecontext(..., (void (*)(void)) X::proxy, ...);

ضد

extern "C" void proxy(int i) {}
makecontext(..., (void (*)(void)) proxy, ...);

تحرير: هل يمكنك إظهار مترجم أو بنية حيث لا يعمل إصدار الأعضاء الثابت (وليس خطأ في المحول البرمجي)؟

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

المحلول

نعم، أنت محظوظ فقط :) extern "c" هو ربط لغة واحدة بلغة C التي يجب أن يدعمها كل مترجم C ++، بجانب خارجي "C ++" وهو الافتراضي. قد يدعم المجمعون الروابط اللغوية الأخرى. يدعم دول مجلس التعاون الخليجي على سبيل المثال "Java" خارجيا والتي تسمح بالتفاعل مع رمز Java (على الرغم من أن هذا أمر مرهق تماما).

يخبر Extern "C" الترجمة أن وظيفتك قابلة للاستدعاء بواسطة رمز C. يمكن أن يتضمن ذلك، ولكن ليس من الضروري، أن تتضمن اتفاقية الاتصال المناسبة والشاحنات اسم لغة C المناسبة (تسمى أحيانا "الديكور") من بين أمور أخرى حسب التنفيذ. إذا كان لديك وظيفة عضو ثابت، فإن اتفاقية الاتصال الخاصة بها هي واحدة من برنامج التحويل البرمجي C ++ الخاص بك. غالبا ما تكون هي نفسها بالنسبة للمترجم C من هذه المنصة - لذلك قلت أنك محظوظ فقط. إذا كان لديك واجهة برمجة تطبيقات جيم وأنت تمرير مؤشر دالة، فأفضل دائما وضعت واحدة إلى وظيفة معلنة مع "ج" خارجيا

extern "C" void foo() { ... }

على الرغم من أن نوع مؤشر الوظيفة لا يحتوي على مواصفات الارتباط ولكن يبدو

void(*)(void)

الرابط هو جزء لا يتجزأ من النوع - لا يمكنك التعبير عنها مباشرة بدون typedef:

extern "C" typedef void(*extern_c_funptr_t)();

سيتم تنصيب مترجم COMEAU C ++، في وضع صارم، خطأ على سبيل المثال إذا حاولت تعيين عنوان الوظيفة الخارجية "C" أعلاه إلى (void(*)()), ، Beause هذا هو مؤشر إلى وظيفة مع رابط C ++.

نصائح أخرى

لاحظ أن extern C هل مستحسن طريقة التشغيل البيني C / C ++. هنا هو السيد الحديث عن ذلك. لإضافة إلى إجابة Eduffy: لاحظ أن الوظائف والمتغيرات الثابتة في مساحة الاسم العالمية يتم إهمالها. استخدم مساحة اسم مجهول على الأقل.

ارجع الى extern C: إذا لم تستخدم extern، فسيتعين عليك معرفة اسم المشاورة بالضبط واستخدامه. هذا أكثر بكثير من الألم.

extern "C" تعطيل اسم المشاهير اسم مترجم C ++ (الذي هو مطلوب للتحميل الزائد).

إذا كنت تعلن وظيفة في A.CPP static, ، ثم لا يمكن العثور عليها بواسطة B.CPP (بقايا الطعام من ج، وله نفس التأثير لوضع وظيفة داخل مساحة اسم مجهولة).

معظم ما extern "C" هل مترجم إلى حد كبير يعتمد. تتغير العديد من المنصات اسم المشاهير واستدعاء الاتفاقية استنادا إلى الإعلان، ولكن لا يتم تحديد أي من ذلك من قبل المعيار. حقا الشيء الوحيد الذي يتطلبه المعيار هو أن التعليمات البرمجية في الكتلة مستدلة من وظائف C. بالنسبة لسؤالك المحدد، تقول المعيار:

نوعان وظيفة مع روابط بلغة مختلفة أنواع مميزة حتى لو كانت متطابقة بطريقة أخرى.

هذا يعنى extern "C" void proxy(int i) {} و /*extern "C++"*/void proxy(int i) {} لديهم أنواع مختلفة، وكما تؤدي المؤشرات إلى هذه الوظائف أنواع مختلفة أيضا. لا يفشل المترجم برمزك بنفس السبب فلن يفشل جزءا رائعا مثل:

int *foo = (int*)50;
makecontext(..., (void (*)(void)) foo, ...);

قد يعمل هذا الرمز على بعض المنصات، ولكن هذا لا يعني أنه سيعمل على منصة أخرى (حتى إذا كان التحويل البرمجي متوافقا تماما). يمكنك الاستفادة من كيفية عملها منصة خاصة، والتي قد تكون موافقا إذا لم تكن مهتما في كتابة التعليمات البرمجية المحمولة.

أما بالنسبة لوظائف الأعضاء الثابتة، فلن تكون مطلوبة للحصول على this مؤشر لذلك التحويل البرمجي مجاني لعلاجها كدالة غير عضو. مرة أخرى، السلوك هنا هو منصة محددة.

بشكل عام

فصول التخزين:

تستخدم فئات التخزين للإشارة إلى مدة ونطاق متغير أو معرف.

مدة:

تشير المدة إلى مدى عمر متغير.

مجال:

يشير النطاق إلى رؤية المتغير.

فئة تخزين ثابتة:

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

فئة تخزين خارجية:

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

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