كيفية تصميم مكتبة برمجية على لغة الـ C++ 6

    • كيفية تصميم مكتبة برمجية على لغة الـ C++ 6


      بسم الله الرحمن الرحيم
      السلام عليكم و رحمة الله

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



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

      و أبدء معكم بالشرح
      الجزء الأول عمل مشروع لمكتبة برمجية على محرر لغة C++ 6
      الشرح بالصور لهذه العملية فهي بسيطة و سهلة لمن سبق له
      واستخدم هذا المحرر







      Windows Sockets
      msdn.microsoft.com/en-us/library/aa280724.aspx
      Automation
      msdn.microsoft.com/en-us/library/dt80be78(VS.80).aspx











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


      - الجزء الثاني اعداد المكتبة البرمجية

      نبداء بالشرح

      من بعد أن قمنا بالقيام بمشروع مكتبة إرتباط حيوي و نحن الآن نعمل على الملف

      MFC_DLL_LIBRARY.cpp

      وهذا كود لمحتوى الملف كاملا

      PHP كود المصدر

      1. // MFC_DLL_LIBRARY.cpp : Defines the initialization routines for the DLL.
      2. //
      3. #include "stdafx.h"
      4. #include <afxdllx.h>
      5. #ifdef _DEBUG
      6. #define new DEBUG_NEW
      7. #undef THIS_FILE
      8. static char THIS_FILE[] = __FILE__;
      9. #endif
      10. #ifdef MFC_DLL_LIBRARYDLL_EXPORTS
      11. #define MFC_DLL_LIBRARYDLL_API __declspec(dllexport)
      12. #else
      13. #define MFC_DLL_LIBRARYDLL_API __declspec(dllimport)
      14. #endif
      15. #ifdef __cplusplus
      16. extern "C"
      17. {
      18. #endif
      19. MFC_DLL_LIBRARYDLL_API int AfxMsBox(LPCTSTR);
      20. MFC_DLL_LIBRARYDLL_API int CString_Find(int,LPSTR ,LPSTR);
      21. MFC_DLL_LIBRARYDLL_API LPSTR CString_Insert(int,LPSTR,LPSTR);
      22. MFC_DLL_LIBRARYDLL_API int CString_Get_Length(LPSTR);
      23. MFC_DLL_LIBRARYDLL_API LPSTR CString_Replace(LPSTR,LPCTSTR,LPCTSTR);
      24. #ifdef __cplusplus
      25. }
      26. #endif
      27. static AFX_EXTENSION_MODULE MFC_DLL_LIBRARYDLL = { NULL, NULL };
      28. extern "C" int APIENTRY
      29. DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
      30. {
      31. // Remove this if you use lpReserved
      32. UNREFERENCED_PARAMETER(lpReserved);
      33. if (dwReason == DLL_PROCESS_ATTACH)
      34. {
      35. TRACE0("MFC_DLL_LIBRARY.DLL Initializing!\n");
      36. // Extension DLL one-time initialization
      37. if (!AfxInitExtensionModule(MFC_DLL_LIBRARYDLL, hInstance))
      38. return 0;
      39. // Insert this DLL into the resource chain
      40. // NOTE: If this Extension DLL is being implicitly linked to by
      41. // an MFC Regular DLL (such as an ActiveX Control)
      42. // instead of an MFC application, then you will want to
      43. // remove this line from DllMain and put it in a separate
      44. // function exported from this Extension DLL. The Regular DLL
      45. // that uses this Extension DLL should then explicitly call that
      46. // function to initialize this Extension DLL. Otherwise,
      47. // the CDynLinkLibrary object will not be attached to the
      48. // Regular DLL's resource chain, and serious problems will
      49. // result.
      50. new CDynLinkLibrary(MFC_DLL_LIBRARYDLL);
      51. }
      52. else if (dwReason == DLL_PROCESS_DETACH)
      53. {
      54. TRACE0("MFC_DLL_LIBRARY.DLL Terminating!\n");
      55. // Terminate the library before destructors are called
      56. AfxTermExtensionModule(MFC_DLL_LIBRARYDLL);
      57. }
      58. return 1; // ok
      59. }
      60. int AfxMsBox(LPCTSTR TXT1)
      61. {
      62. if (AfxMessageBox(TXT1)) {return 1;}
      63. return 0;
      64. }
      65. int CString_Find(int nStart ,LPSTR FSTR ,LPSTR FSUBSTR)
      66. {
      67. return CString(FSTR).Find(FSUBSTR,nStart);
      68. }
      69. LPSTR CString_Insert(int nIndex ,LPSTR ISTR ,LPSTR ISUBSTR)
      70. {
      71. CString ISTR2 = ISTR;
      72. ISTR2.Insert(nIndex,ISUBSTR);
      73. return (LPSTR) ISTR2.GetBuffer(ISTR2.GetLength());
      74. }
      75. int CString_Get_Length(LPSTR GLSTR)
      76. {
      77. return CString(GLSTR).GetLength();
      78. }
      79. LPSTR CString_Replace(LPSTR RSTR, LPCTSTR ipszOld , LPCTSTR ipszNew)
      80. {
      81. CString RSTR2 = RSTR;
      82. RSTR2.Replace(ipszOld,ipszNew);
      83. return (LPSTR) RSTR2.GetBuffer(RSTR2.GetLength());
      84. }
      عرض الكل

      أولا سنقوم بإعداد المكتبة البرمجية حتى يمكنها إستقبال الإتصال و أيضا تضمين
      ميزة الإتصال بها عن طريق لغة السي بلس و باقي اللغات

      PHP كود المصدر

      1. #ifdef MFC_DLL_LIBRARYDLL_EXPORTS
      2. #define MFC_DLL_LIBRARYDLL_API __declspec(dllexport)
      3. #else
      4. #define MFC_DLL_LIBRARYDLL_API __declspec(dllimport)
      5. #endif


      يتضح من هذه العملية بأن هناك نوعين من الإتصال بمكتبة الإرتباط الحيوي و ما يحدد نوع
      الإتصال هووه طريقة الإتصال التي تصدر من التطبيق و الذي يستخدم هذه المكتبة و هذه
      بعض من طرق الإتصال بمكتبات الإرتباط الحيوي

      PHP كود المصدر

      1. HMODULE HMO = LoadLibrary(_T("MFC_DLL_LIBRARY.dll"));

      / أولا أمر تحميل أو رفع المكتبة البرمجية

      PHP كود المصدر

      1. typedef int (*parameters) (int,LPSTR,LPSTR);

      / ثانيا نقوم بعمل struct يطابق أنواع متغيرات الوظيفة و ترتيبها

      PHP كود المصدر

      1. parameters Proc = (parameters) GetProcAddress(HMO,_T("CString_Find"));

      msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx
      /ثالثا نقوم باستجلاب عنوان الوظيفة الموجودة على المكتبة البرمجية و التي تظهر باسم
      /CString_Find

      PHP كود المصدر

      1. Proc( nStart ,FSTR,FSUBSTR);

      /من بعد نقوم باتصال عادي بالوظيفة

      نوع أخر من أنواع الإتصال بالمكتبات البرمجية تاليا

      PHP كود المصدر

      1. [DllImport('MFC_DLL_LIBRARY.dll', CharSet = CharSet.Unicode)]
      2. public static extern int CString_Find(int nStart ,LPSTR FSTR ,LPSTR FSUBSTR);


      و كما نلاحض بأن لكل النوعين من الإتصال كلمة محجوزة أو مفتاحية
      أو أساسية تختص به

      النوع الأول
      تختص به الكلمة المحجوزة التالية

      PHP كود المصدر

      1. __declspec(dllexport)

      msdn.microsoft.com/en-us/library/a90k134d(VS.80).aspx

      و النوع الثاني
      تختص به الكلمة المحجوزة التالية

      PHP كود المصدر

      1. __declspec(dllimport)

      msdn.microsoft.com/en-us/library/3y1sfaz2(VS.80).aspx


      MFC_DLL_LIBRARYDLL_EXPORTS

      هذا الجزء التالي
      MFC_DLL_LIBRARYDLL
      اسم مكتبة الإرتباط الحيوي

      _EXPORTS
      تصنف على أنها أحد خصائص وصلات مكتبات الإرتباط الحيوي
      Linker Options
      msdn.microsoft.com/en-us/library/y0zzbyt4(VS.71).aspx
      وهي ما تميز بين نوعية إتصال و أخر بمكتبة الإرتباط الحيوي

      و بهذه الدالة الشرطية يمكن للمكتبة أن تعمل على النوعين من الإتصال
      و طبعا بلإمكان جعل المكتبة البرمجية تعمل نوع واحد محدد من الإتصال
      كمثالا هذه الطريقة

      PHP كود المصدر

      1. #define MFC_DLL_LIBRARYDLL_API __declspec(dllexport)

      لوحدها

      أو بهذه الطريقة

      PHP كود المصدر

      1. #define MFC_DLL_LIBRARYDLL_API __declspec(dllexport)

      لوحدها

      أي جعلنا قيمة المتغير
      MFC_DLL_LIBRARYDLL_API
      مساوية لقيمة الكلمة المحجوزة أو الأساسية و التي تناسب
      نوعية الإتصال لكي نقوم فيما بعد باستخدام هذا المتغير


      - جعل مكتبة الإرتباط الحيوي تستقبل الإتصال بوظائفها من جميع
      اللغات البرمجية المتاحة بمافيها الـ C++

      PHP كود المصدر

      1. #ifdef __cplusplus
      2. extern "C"
      3. {
      4. #endif
      5. MFC_DLL_LIBRARYDLL_API int AfxMsBox(LPCTSTR);
      6. MFC_DLL_LIBRARYDLL_API int CString_Find(int,LPSTR ,LPSTR);
      7. MFC_DLL_LIBRARYDLL_API LPSTR CString_Insert(int,LPSTR,LPSTR);
      8. MFC_DLL_LIBRARYDLL_API int CString_Get_Length(LPSTR);
      9. MFC_DLL_LIBRARYDLL_API LPSTR CString_Replace(LPSTR,LPCTSTR,LPCTSTR);
      10. #ifdef __cplusplus
      11. }
      12. #endif
      عرض الكل


      PHP كود المصدر

      1. __cplusplus

      عبارة عن macro يدلك على أن اللغة التي يتم الإتصال منها بالمكتبة
      البرمجية هي لغة السي بلس
      msdn.microsoft.com/en-us/library/ys435b3s(VS.80).aspx

      PHP كود المصدر

      1. extern "C"

      كلمة محجوزة أو أساسية أو مفتاحية تسمح بلإتصال بالوظائف function
      عبر وصلات الإرتباط الحيوي و عن طريق تطبيقات مصممة على لغات السي بلس
      msdn.microsoft.com/en-us/library/0603949d(VS.80).aspx
      و بذالك ستعمل المكتبة على جميع اللغات البرمجية بما فيها السي بلس

      طبعا هناك قوس مفتوح يجب إغلاقة بالقوس المعاكس كتالي

      PHP كود المصدر

      1. #ifdef __cplusplus
      2. }
      3. #endif


      توضيح لهذه العملية كاملة أولا هذه العملية يتم تنفيذها على
      ما يسمى Declaration الوظائف وهذا هووه Declaration
      الوظيفة الأولى بالكود التالي

      PHP كود المصدر

      1. int AfxMsBox(LPCTSTR);


      نظيف عليه أولا في حالة الإتصال من تطبيقات مصممة
      على لغة السي بلس الكلمة الLحجوزة

      PHP كود المصدر

      1. extern "C"


      ثم من بعد نضيف المتغير الذي عوضنا عنه بإحدى الكلمات المحجوزة التالية

      PHP كود المصدر

      1. __declspec(dllexport)

      و

      PHP كود المصدر

      1. __declspec(dllimport)


      و هذا هووه المتغير
      MFC_DLL_LIBRARYDLL_API

      و طبعا ما يحدد أي واحدة من بين هذه الكلمات المحجوزة هووه نوعية
      الإتصال الصادر من التطبيق و الذي يقوم بإجراء الإتصال بالمكتبة
      و ستكون النتائج حسب الإحتمالات التالية

      PHP كود المصدر

      1. _declspec(dllexport) int AfxMsBox(LPCTSTR);

      أو

      PHP كود المصدر

      1. __declspec(dllimport) int AfxMsBox(LPCTSTR);

      أو

      PHP كود المصدر

      1. extern "C" __declspec(dllexport) int AfxMsBox(LPCTSTR);

      أو

      PHP كود المصدر

      1. extern "C" __declspec(dllimport) int AfxMsBox(LPCTSTR);

      ومن بعد نقوم بعمل الوظائف و ما تحتوي من عمليات منطقية


      - كيفية الإتصال بالمكتبة البرمجية عن طريق تطبيق مصمم على لغة الـ C++ 6

      هذه هي الوظيفة الموجودة على مكتبة الإرتباط الحيوي و التي سنقوم
      بلإتصال بها عن طريق برنامج مصمم على لغة C++6

      PHP كود المصدر

      1. int CString_Find(int nStart ,LPSTR FSTR ,LPSTR FSUBSTR)
      2. {
      3. return CString(FSTR).Find(FSUBSTR,nStart);
      4. }


      - الإتصال بالمكتبة البرمجية

      PHP كود المصدر

      1. HMODULE HMO = LoadLibrary(_T("MFC_DLL_LIBRARY.dll"));

      / أولا أمر تحميل أو رفع المكتبة البرمجية

      PHP كود المصدر

      1. typedef int (*parameters) (int,LPSTR,LPSTR);

      / ثانيا نقوم بعمل struct يطابق نوعية متغيرات الوظيفة و ترتيبها

      PHP كود المصدر

      1. parameters Proc = (parameters) GetProcAddress(HMO,_T("CString_Find"));

      msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx
      /ثالثا نقوم باستجلاب عنوان الوظيفة الموجودة على المكتبة البرمجية و التي تظهر باسم
      /CString_Find

      PHP كود المصدر

      1. Proc( nStart ,FSTR,FSUBSTR);


      /من بعد نقوم باتصال عادي بالوظيفة

      توضيح أكثر لعملية الإتصال

      PHP كود المصدر

      1. int CString_Find(int nStart ,LPSTR FSTR ,LPSTR FSUBSTR)
      2. {
      3. return CString(FSTR).Find(FSUBSTR,nStart);
      4. }


      أولا توضيح لما يسمى الـ struct

      PHP كود المصدر

      1. typedef int (*parameters) (int,LPSTR,LPSTR);

      / ثانيا نقوم بعمل struct يطابق نوعية متغيرات الوظيفة و ترتيبها

      طبعا الوظيفة تحتوي على متغير تحدد نوعيته نوعية بيانات النتائج التي سترجع من بعد الإتصال
      بالوظيفة و إتمام العمليات المنطقية بها و ههوه بنفس نوع المتغير الذي يتم إرجاعه عن طريق الأمر
      return و و بهذه الوظيفة هووه بنوع int و نلاحضه في هذا الجزء من الـ struct
      typedef int

      *parameters
      هووه متغير يحمل قيمة struct كاملة على شكل ما يسمى pointer

      PHP كود المصدر

      1. (int,LPSTR,LPSTR);

      أما هذا الجزء فهووه يمثل نوعية متغيرات الوظيفة بنفس
      الترتيب الموجودة عليه بالوظيفة نفسها

      PHP كود المصدر

      1. parameters Proc = (parameters) GetProcAddress(HMO,_T("CString_Find"));

      نقوم في هذه العملية عن طريق الأمر GetProcAddress
      باستدعاء عنوان الوظيفة من مكتبة الإرتباط الحيوي و جعل هذا العنوان
      يتماثل مع حالة المتغير parameters الذي قمنا بعمله حسب تنظيم ونوعية
      متغيرات الوظيفة وههووه نيجة الـ struct

      PHP كود المصدر

      1. Proc( nStart ,FSTR,FSUBSTR);

      وفي هذا الجزء نحن نتصل بالوظيفة

      صورة تطبيق الإتصال بالمكتبة البرمجية


      الملفات الرائيسية لمشروع عمل مكتبة إرتباط حيوي و أيضا الملفات الرائيسية
      لمشروع تطبيق يقوم بلإتصال بالمكتبة البرمجية مع المكتبة و التطبيق جاهزان
      من المرفقات


      المشروعان كاملان بكافة الملفات من هذا الرابط
      file-upload.eu/download-1520790/MyProjects.zip.html

      تم تحرير الموضوع 1 مرة, آخر مرة بواسطة ناقوس الخطر ().