سؤال

لنفترض أن لدينا DLL ويجب أن يكون هناك صفيف مخزّن عالميًا فيه سيتم تصديره ، والشيء هو أننا نريد تهيئته من خلال قراءة بعض المحتوى من ملف ، لذلك أنا شخصياً لا أجد نفسي طريقة أخرى غير وضع طريقة أخرى في البنية لتكون قادرة على التهيئة باستخدام مُنشئ:

struct Construction{
 public:
  Construction(){
   //do the initialization thing and read the needed data from the file
  }
  SomeType sTArray[100];
};

__declspec(dllexport) Construction obj();

الآن حيث سيتم استخدامه ، يمكن للمبرمج تهيئة مرجع إليه ثم استخدام المرجع كما هو أدناه:

SomeType (&arrayRef)[100]=obj.sTArray;

الآن هل تعتقد أنني مخطئ في أي سياق؟

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

المحلول

نعم ، لقد قمت بإعداد نفسك لمفاجأة سيئة للغاية في مرحلة ما.

  1. يتم تشغيل منشئي الكائنات العالمية أثناء بدء تشغيل C -Runtime لـ DLL.
  2. يعمل رمز بدء التشغيل C أثناء DLLMAIN.
  3. أثناء dllmain ، أنت تمسك قفل محمل DLL.
  4. قد يتضمن مُنشئ الكائنات مكالمات لـ Win32 API التي تقوم بتحميل نظام DLL الآخر.
  5. تتجه لتحميل DLL آخر أثناء حمل قفل DLL Loader بالفعل إلى موت سريع لعملية الخاص بك.

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

struct Construction{
public:
  Construction() : bInit(false) {};
  SomeType* GetArray()
  {
    if(!bInit)
    {
      //do the initialization thing and read the needed data from the file
      bInit = true;
    }
    return sTArray;
  };
private:
  SomeType sTArray[100];
  bool bInit;
};

__declspec(dllexport) Construction obj();

بالطبع ، يجب تقسيم هذا إلى ملفات منفصلة وتنفيذ.

نصائح أخرى

نظرًا لأن CRT في DLL وفي القابل للتنفيذ قد يكون مختلفًا ، يجب عليك توفير Construction مع release الطريقة التي ستحذف كائن مخصص. وبهذه الطريقة ، ستضمن استدعاء وظيفة التخصيص من CRT المناسب. كما تحتاج إلى العودة Construction بواسطة مؤشر لاستبعاد عمليات النسخ. يوضح الرمز التالي الطريقة التي يمكن بها تنفيذها:

// DLL export header
struct IConstruction {
protected:
  virtual ~IConstruction() {}
public:
  virtual void release() =0;
  virtual SomeType& get_array() =0;
};

__declspec(dllexport) IConstruction* obj();

-

// DLL implementation
struct Construction : public IConstruction {
  SomeType sTArray[100];

  Construction() { /* do initialization */ }
  virtual void release() { delete this; }
  virtual SomeType& get_array() { return sTArray; }
  virtual ~Construction() { /* do clean up */ }    
};

IConstruction* obj() { return new Construction; }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top