سؤال

أنا أتخذ دورة لغات البرمجة ونحن نتحدث عن extern "C" إعلان.

كيف يعمل هذا الإعلان على مستوى أعمق آخر غير "واجهات C و C ++"؟ كيف يؤثر هذا على الارتباطات التي تحدث في البرنامج كذلك؟

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

المحلول

extern "C" يستخدم للتأكد من أن الرموز التالية ليست كذلك مانج (مزين).


مثال:

دعنا نقول أن لدينا التعليمة البرمجية التالية في ملف يسمى test.cpp:

extern "C" {
  int foo() {
    return 1;
  }
}

int bar() {
  return 1;
}

اذا ركضت gcc -c test.cpp -o test.o

إلقاء نظرة على أسماء الرموز:

00000010 ر _z3barv.

00000000 ر فو.

foo() يبقي اسمها.

نصائح أخرى

دعونا نلقي نظرة على وظيفة نموذجية يمكن أن تجميعها في كل من C و C ++:

int Add (int a, int b)
{
    return a+b;
}

الآن في C، تسمى الوظيفة "_add" داخليا. في حين أن وظيفة C ++ تسمى شيئا مختلفا تماما باستخدام نظام يسمى Name Mangling. في الأساس وسيلة لتسمية وظيفة بحيث يكون له نفس الوظيفة مع معلمات مختلفة اسم داخلي مختلف.

لذلك إذا تم تعريف الإضافة () في Add.C، ولديك النموذج الأولي في Add.h الذي ستحصل عليه إذا حاولت تضمين add.h في ملف C ++. نظرا لأن رمز C ++ يبحث عن وظيفة باسم مختلفة إلى واحد في add.c ستحصل على خطأ رابط. للحصول على هذه المشكلة، يجب عليك تضمين add.c بواسطة هذه الطريقة:

extern "C"
{
#include "add.h"
}

الآن رمز C ++ سوف يربط مع _ADD بدلا من إصدار اسم C ++.

هذا واحد من استخدامات التعبير. خلاصة القول، إذا كنت بحاجة إلى ترجمة التعليمات البرمجية التي تكون صارمة C في برنامج C ++ (عبر عبارة FILE أو بعض الوسائل الأخرى)، تحتاج إلى لفه بإعلان خارجي "C" {...}.

عندما تقوم بعلم كتلة من التعليمات البرمجية ذات المستوى الخارجي "C"، فأنت تخبر النظام باستخدام رابط أسلوب C.

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

في C ++ اسم / رمز الوظائف يتم إعادة تسمية فعلا إلى شيء آخر بحيث يمكن أن تحتوي فئات / المسامحات السمعية المختلفة على وظائف من نفس التوقيعات. في ج، فإن الوظائف هي جميعها محددة عالميا وليس هناك حاجة إلى هذه العملية إعادة تسمية مخصصة.

لجعل C ++ و C، تحدث مع بعضها البعض، "EXTERN C" يرشد المحول البرمجي عدم استخدام اتفاقية C.

تجدر الإشارة إلى ذلك extern "C" يعدل أيضا أنواع الوظائف. لا يعدل الأشياء فقط على المستويات المنخفضة:

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

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

نوع من &foo لا يساوي النوع الذي يعينه typedef (على الرغم من أن الرمز مقبول من قبل البعض، ولكن ليس جميع المحامرة).

يؤثر Extern C اسم المشاهير بواسطة برنامج التحويل البرمجي C ++. في طريقة الحصول على مترجم C ++ لعدم أسماء Mangle، أو بدلا من تناولها بنفس الطريقة التي سيحدث فيها مترجم C. هذه هي الطريقة التي تتناولها واجهات C و C ++.

كمثال:

extern "C" void foo(int i);

سيسمح لتنفيذ الوظيفة في وحدة نمطية ج، ولكن السماح بإمدادها من وحدة نمطية C ++.

تأتي المشكلة عند محاولة الحصول على وحدة نمطية C للاتصال بوظيفة C ++ (من الواضح أن C لا يمكن استخدام فئات C ++) المعرفة في وحدة نمطية C ++. مترجم C لا يحب extern "C".

لذلك تحتاج إلى استخدام هذا:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

الآن عندما يظهر هذا في ملف رأس، ستكون كل من محطات التحويل البرمجيات C + C ++ سعداء بالإعلان ويمكن الآن تحديدها في وحدة نمطية C أو C ++، ويمكن استدعاء كلا من التعليمات البرمجية C و C ++.

extern "C" يدل على أن الرمز المرفق يستخدم ربط نمط C واسم المشاهير. يستخدم C ++ تنسيق اسمحوا اسم أكثر تعقيدا. إليك مثال:

http://en.wikipedia.org/wiki/name_mangling.

int example(int alpha, char beta);

في ج: _example

في C ++: __Z7exampleic

تحديث: كما يلاحظ Gmannickg في التعليقات، فإن نمط اسم الاسم يعتمد على مترجم.

Extern "C"، هي كلمة رئيسية لإعلان وظيفة مع ربط C، لأن COMPILEER C ++ سيقوم بترجمة المصدر إلى نموذج مختلف في ملف الكائنات:

على سبيل المثال، مقتطف رمز كما يلي:

int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}

سيتم ترجمة Compilers C 32 بت ترجمة التعليمات البرمجية في النموذج كما يلي:

_func1
_func2@4
@func3@4

في CDECL، سيتم ترجمة FUNCR1 باسم "_اسم'

في STDCall، سيتم ترجمة FUNC2 باسم "_name @ X.'

في fastcall، سوف funct2 سوف يترجم كما هو@ اسم @ x'

'عاشريعني عدد البايتات من المعلمات في قائمة المعلمات.

اتفاقية 64 بت على ويندوز لا يوجد لديه السفلية الرائدة

في C ++، يتم تقديم الفصول، القوالب، مساحات المساحات السمعية وتحفيز المشغل، نظرا لأنه غير مسموح به وظيفتين بنفس الاسم، يوفر برنامج C ++ برنامج التحويل البرمجي معلومات النوع في اسم الرمز،

على سبيل المثال، مقتطف رمز كما يلي:

int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}

سيقوم برنامج التحويل البرمجي C ++ بترجمة التعليمات البرمجية كما يلي:

int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}

"_v" و "_i" هي معلومات النوع من "الفراغ" و "int"

هنا اقتباس من MSDN

"تعلن الكلمة الرئيسية الخارجية متغير أو وظيفة وتحديد أنه يحتوي على رابط خارجي (اسمه مرئيا من الملفات غير المرغوب فيه). عند تعديل متغير، يحدد Execual أن المتغير يحتوي على مدة ثابتة (يتم تخصيصه عندما يبدأ البرنامج ومعامله عند انتهاء البرنامج). قد يتم تعريف المتغير أو الوظيفة في ملف مصدر آخر، أو في وقت لاحق في نفس الملف. تصريحات المتغيرات والوظائف في نطاق الملفات هي خارجية افتراضي. "

http://msdn.microsoft.com/en-us/library/0603949d٪28vs.80٪29.aspx.

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