سؤال

لقد قمت بتطبيق "نظام إضافي" أساسي جدًا كجزء من ملف مكتبة ثابتة.ينفذ كل "مكون إضافي" الدعم لتنسيق صورة معين، على سبيل المثال.جيف، جبيغ، الخ.علاوة على ذلك، لديّ Singleton (فئة تسمى PluginManager) الذي يحتفظ بقائمة بجميع المكونات الإضافية المتاحة.

الجزء الصعب هو أنني أريد تعطيل/تمكين المكونات الإضافية عن طريق إضافة أو إزالة ملفاتها المصدر من ملف المشروع.ولتحقيق ذلك، يقوم كل مكون إضافي بإنشاء متغير عام (بأسماء مختلفة) ويسجل المكون الإضافي في مُنشئ تلك الفئة إلى PluginManager.

شيء من هذا القبيل لتنسيق JPEG ...

struct JPEGPlugin
{
  // constructor will register plugin
  JPEGPlugin()
  {
    PluginManager::Singleton().RegisterPlugin(this);
  }

  // plenty of other code
  ...
};

JPEGPlugin jpeg_instance;  // instantiate in global scope

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

لقد واجهت هذه المشاكل عدة مرات على مر السنين، وبحثت دائمًا في الإنترنت عن الحلول.في كل مرة، كنت أجد صفحات تقول بشكل أساسي أن هذه مشكلة معروفة وأنه يجب علي التعايش معها.

ولكن ربما يعرف شخص ما في SO كيفية جعل هذا يعمل؟

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

المحلول

وأنا لا أعرف إذا كان هذا حلا لطريقة حل هذه المشكلة، ولكن كان لدينا مشكلة مماثلة مع تسجيل ثابت من مصنع الكائن وفي Visual Studio نحن حلها من خلال الإعلان الطبقات المعنية مع __declspec (dllexport) ان هذه الخطوة ضرورية حتى ولو كانت المكتبات المشاركة لا دلس. ولكن من دون هذا من شأنه أن رابط بحذف فصول لا المشار إليه.

والحل التسجيل عملنا مختلفة قليلا ولا تنطوي على المكدس تخصيص الكائنات. أنا رفعت أجزاء من CPP وحدة، وهذا هو أيضا حيث اكتشفت IIRC نهج __declspec.

[عدل] ونحن أيضا ل#include إعلان لفئة مسجلة من جزء من التعليمات البرمجية.

نصائح أخرى

ونظرا لأنه هو libary ثابت، قد تنظر في وجود مدير تسجيل المحمول (بدلا من الإضافات تسجيل أنفسهم). ملف الرأس يمكن أن تحدد بعض رمز preproc (أي JPEG_PLUGIN) التي تسيطر على ما إذا كان أو لم يكن مدير يسجل المساعد بناء على إدراج الرأس:

#include "JpegPlugin.h"

void PluginManager::RegisterPlugins()
{
#idef JPEG_PLUGIN
    RegisterPlugin(&jpeg_instance);
#endif
}

وJpegPlugin.h لا تحتاج بالضرورة لتشمل تعريف JpegPlugin. ويمكن أن يكون شيء من هذا القبيل:

#ifndef JPEG_PLUGIN_HEADER
#define JPEG_PLUGIN_HEADER

#if 0 // change this to 1 to use the plugin
#define JPEG_PLUGIN
#include "Jpeg_PluginCls.h"
#endif

#endif

وهذا هو متابعة ل هارالد Scheirich في الإجابة .

ولقد فعلت بعض تجريب، ويبدو أن الوضع الإصدار MSVC ++ 2005 (ولكن ليس تصحيح الوضع) سوف تتحول على العلم /OPT:REF إلى رابط، والتي وفقا لفي وثائق LINK ، وسوف يسبب أي حرف غير مرجعية لإزالتها من EXE النهائي. و، صفحة ويب ل__declspec(selectany) يبدو أنها تشير إلى أن منشئات للكائنات العالمية لا ينظر إليها على أنها إشارات إلى كائن (بشكل غير صحيح IMHO، ولكن هناك لديك). لذا فان تخميني هو أن هذه المشكلة "يذهب بعيدا" ليبني التصحيح - فهل هذا صحيح

وهكذا، وأعتقد أن اقتراح هارالد لاستخدام __declspec(dllexport) هو وسيلة مريحة لوضع العلامات والرموز كما هو موضح "إلى" لأنه تم تحديد داخل شفرة المصدر. إذا لسبب ما كنت تريد تجنب تصدير رمز، وأظن أنك يمكن أن تنجز الشيء نفسه إما عن طريق استخدام في /INCLUDE:mysymbol رابط العلم أو إيقاف العلم /OPT:REF.

لو سمحت:

  1. أضف مشروع lib الثابت كمرجع لمشروع exe
  2. قم بتعيين كلاً من "تبعيات مكتبة الارتباط" و"استخدام تبعية مكتبة الارتباط كمدخلات" على أنها صحيحة.

انظر الى هذا:config

عند تعيين "استخدام تبعية مكتبة الارتباط كمدخلات" على نعم، يرتبط نظام المشروع في ملفات .obj لـ .libs التي تنتجها المشاريع التابعة.لذلك يتم الاحتفاظ بجميع الرموز.

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