سؤال

رأس التصدير DLL

extern "C"
void _declspec(dllexport) __stdcall foo();

ملف .def

EXPORTS
foo         @1

عندما أقوم بإنشاء DLL بواسطة تكوين 64 بت بني ، أقابل هذا التحذير.

تحذير LNK4197: تصدير "فو" المحدد عدة مرات ؛ باستخدام المواصفات الأولى

ولكن إذا قمت ببناء DLL بواسطة تكوين بناء 32 بت ، فإن التحذير لا يحدث أبدًا.
ما المشكلة؟ ماهو الفرق.

في رأس DLL للواجهة ، عادة ما نستخدم هذه التقنية ،

#ifdef EXPORT_DLL
#define BASICAPI _declspec(dllexport)
#else
#define BASICAPI _declspec(dllimport)
#endif //_EXPORT_DLL

ولكن إذا كان ملف DEF موجودًا أيضًا ، فسوف نلتقي دائمًا بالتحذير عندما نقوم ببناء 64 بت DLL.
لذلك ، هل يجب أن نكتب الرموز مثل هذا؟

#ifdef EXPORT_DLL
#define BASICAPI
#else
#define BASICAPI _declspec(dllimport)
#endif //_EXPORT_DLL

أنه يعمل بشكل جيد. لكنها ليست مألوفة بالنسبة لي.
أعطني أي آرائك.

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

المحلول

عمومًا ليس من الممارسات الجيدة تحديد الصادرات مرتين لنفس الوظيفة. إذا كان لديك بالفعل __declspec(dllexport) ثم لا تحتاج إلى تحديد التصدير في ملف .DEF أيضًا. على العكس ، إذا كان لديك التصدير المدرج في ملف .def ، فلا داعي ل __declspec(dllexport).

أعتقد أن سبب التحذير هو أن البناء في x86 ، __declspec(dllexport) يقوم بتصدير الاسم المزين بأحد السطح السطحي الرائد ، لكن برنامج التحويل البرمجي 64 بت لا يزين أسماء مع السطح السفلي الرائد ، مما يؤدي إلى مكرر. للتحقق من ذلك ، يمكنك أن تنظر إلى DLL 32 بت في Walker التبعية ، ويجب أن ترى وظيفتين تم تصديرهما ، "Foo" و "_foo".

نصائح أخرى

__declspec(dllexport) و .def ملفات اثنين مختلف طرق لتصدير الرموز من DLL. لا تحتاج إلى كليهما وينبغي أن تحذفهم. ال __declspec تعد الطريقة أكثر تنوعًا بالنسبة لبرامج C ++ حيث تصدر أسماء مع c ++ millgling ، مما يتيح تصدير الوظائف المحملة الزائدة ، ولكن على العكس من ذلك يجعل الأسماء أكثر صعوبة في الاستيراد عبر getProcadDress.

أيضا ، باستخدام ماكرو عام مثل EXPORT_DLL أمر خطير لأنه يعني أنه لا يمكنك بناء DLL ، الذي يستخدم DLL آخر ، دون أن يحاول DLL واحد تصدير جميع رموز كلا DLL.

يقوم DevStudio تلقائيًا بإنشاء رمز على مشاريع DLL: <PROJECT>_EXPORTS مما يجعل الأمر سهلاً وآمنًا لإنشاء ماكرو تصدير:

#ifdef EXPORT
#undef EXPORT
#endif
#ifdef PROJECTNAMEHERE_EXPORTS
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

EXTERN_C EXPORT void __stdcall Function1(void);
EXTERN_C EXPORT void __cdecl Function2(...);
         EXPORT void Function3(void);

يمكن الحصول على وظائف 1 و 2 مع getProcaddress _Function1@0 و Function2 على التوالى. سيتم تصدير Function3 من خلال اسم مشوهة محددًا بمترجم سيبدو مثل: @Function3@@UAG_DB@Z. هذا الاسم مختلف لكل تحميل زائد من الوظيفة ، وهو ما يسمح بالحمل الزائد للعمل.

من المهم معرفة اسم التشويش __declspec كملفات .def لا تهتم وستصدر فقط Function1, Function2 و Function3.

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