رفتن به مطلب
جامعه‌ی برنامه‌نویسان مُدرن ایران

فرهاد شیری

مدیران مرجع
  • تعداد ارسال ها

    58
  • تاریخ عضویت

  • آخرین بازدید

  • روز های برد

    14

آخرین بار برد فرهاد شیری در 25 دی

فرهاد شیری یکی از رکورد داران بیشترین تعداد پسند مطالب است !

اعتبار در سایت

70 عالی

2 دنبال کننده

درباره فرهاد شیری

توسعه‌ دهنده بَک اِند
توسعه‌ دهنده فرانت اِند
اساتید
  • تاریخ تولد 20 مهر 1360

موقعیت

  • شهر
    تهران

آخرین بازدید کنندگان نمایه

242 بازدید کننده نمایه
  1. نحوه ساخت یک کتابخانه (Shared Object (.so در سیستم عامل لینوکس توسط کامپایلر GCC مرحله 1: ابتدا باید در برنامه ای که قصد دارید آن را به کتابخانه عمومی تبدیل کنید باید یک رابط مناسب Factory Method برای لینک در زمان اجرا بسازید. نکته! توجه داشته باشید که می توانید با استفاده از پلی مورفیسم یک اشاره گر از یک رابط که به صورت مجرد تعریف شده است را در Factory Method کتابخانه خود انتقال دهید. تابع سازنده رابط کتابخانه را به شکل زیر در Main برنامه کتابخانه تعریف کنید...! #include "encryptorPlugin.h" extern "C" { extern PluginEnctyptorPtr create_plugin() { return PluginEnctyptorPtr(new encryptor_plugin); } extern bool destroy_plugin(PluginEnctyptorPtr instance) { if(instance !=NULL){ instance =NULL; delete instance; return true; } return false; } } int main(int argc, char *argv[]) { return 0; } مرحله 2: در این مرحله باید یک کلاس مجرد بسازید و متدهایی که باید زمان فراخوانی اشاره گر کلاس به آنها دسترسی داشته باشید را تعریف نمایید. مانند کلاس زیر که من تعریف کرده ام... #ifndef __PLUGIN_H__ #define __PLUGIN_H__ #include <sstream> #include <string.h> typedef char* Bytes; typedef unsigned int size_t; typedef const char* cBytes; #define DELOBJ(obj) {if(obj!=NULL){delete obj;obj=NULL;}} enum encryptAloglType { BASE64, HASH , MD4 ,MD5 ,OPENSSL }; enum ioType { CPP_STREAM , C_LOWLEVEL }; class Encryptor_Interface { public: virtual ~Encryptor_Interface() {} virtual void getEncBuffer(Bytes & buffer, cBytes fileName) const = 0; virtual void getDecBuffer(std::istringstream** sstream, cBytes fileName) const = 0; virtual void setIoType(ioType =C_LOWLEVEL) = 0; virtual void setAlgolType(encryptAloglType) = 0; virtual void dispose(int) =0; virtual size_t getReadedSize() =0; }; typedef Plugin_Interface* PluginEnctyptorPtr; #endif // __PLUGIN_H__ class ISCLVoterManager { public: virtual ~ISCLVoterManager(){}; virtual bool Init(int nSysID,int nNodeID,const char* strFileName) = 0; connections }; مرحله 3: در این مرحله بعد از پیاده سازی الگوریتم های متدهای کلاس مجرد ساخته شده باید سورس کتابخانه خود را در لینوکس کامپایل کنید. اگر توزیع لینوکس شما از bash استفاده میکند می توانید به روش زیر کامپایل را انجام دهید... gcc -ggdb3 -shared -fPIC libdep.c -o libEncryptor.so در این مرحله در صورتی که خطایی وجود نداشته باشد باید کتابخانه شما کامپایل شده باشد البته به صورت Shared Library. مرحله 4: اکنون در این مرحله کافی است که از رابط زیر که من به صورت template نوشته ام به صورتی که به اشاره خواهم کرد استفاده نمایید. در این کلاس کافی است که شما رابط مجرد کتابخانه را به صورت اشاره گر ویا در صورتی که متدهای شما در کتابخانه به آرگومانهایی نیاز دارند به همراه آرگومانهای کلاس را به سازنده این کلاس ارسال نمایید. در این کلاس با استفاده از تکنیک استراتژی شما می توانید انوع رابط های کتابخانه ها را به راحتی استفاده نمایید فقط کافی است که یک کلاس Wrapper بنویسید که کلاس مجرد Solver را به ارث برده باشد و در متد solve این کلاس نحوه پیاده سازی کتابخانه خود را بنویسید. زمانی که شما در پروژه های خیلی بزرگ کار میکنید که از چند ده کتابخانه مختلف استفاده میکنند به راحتی می توانید از این کلاس ژنریک استفاده نمایید تا هم اتصالات سخت را از بین برده باشید و هم کلاس های سبک رابطی را تهیه کرده اید که اصل Single Responsibility را هم به خوبی راعایت کرده باشید وهم کسانی که از رابط شما استفاده میکنند درگیر جزییات پیاده سازی نخواهند شد. /* * Library_Loader.h * * Created on: Jan 1, 2019 * Author: f.shiri */ #ifndef PLUGINLOADER_H_ #define PLUGINLOADER_H_ #include "Encryptor_interface.h" #include <stdexcept> #include <memory> #include <dlfcn.h> #define LibEncryptorName "./libEncryptor.so" #define LibFactoryMethod "create_plugin" #define LibDestyoryMethod "destroy_plugin" #define LogicFileName "logic.ini" #define __CleanupLibClose __attribute__((cleanup(closedl))) #ifdef SCL_EQUIPPED #include "SCLVoter_Interface.h" #include "initsclvoter.h" extern ISCLVoterManager* pSCLVoterManager; #endif typedef Encryptor_Interface* encAbstractPtr; //typedef ISCLVoterManager* pISCLVoter; /* load shared library or static library and dynamic * declare library virtual function. * template arg1 : interface class library pointer. * */ template<class InterfacePtr> class PluginLoader { private: /*clean up macro function calling by compiler, delete the pointer when the pointer's life cycle is end */ static inline int closedl(void* handle) { int tmp = -1; if (handle) tmp = dlclose(handle); handle = NULL; return tmp; } struct { /* union data type contained * dynamic link library objects. * */ union { void* dlsym; InterfacePtr (*factoryMethod)(); } factoryObject; union { void* dlsym; bool (*destoryMethod)(InterfacePtr); } destroyObject; /* shared library handler */ } libraryObject; void* m_handle; public: explicit PluginLoader() { } ; ~PluginLoader() { } ; // Dynamic load, encryption function from shared library. /* * arg1 : shared library name. * arg2 : reference factory method name in shared library. * arg3 : reference declarative interface class pointer. * arg4 : own request for the symbol in library or main executable. // arg5 : reference destroy method name in shared library. * return type : reference interface pointer. */ template<class CInterfacePtr> inline void operator()(cBytes libName, cBytes factoryFuncName, CInterfacePtr** pClassInterface,cBytes destroyFuncName =NULL) { dlerror(); /* * The RTLD_DEEPBIND attribute specifies that when resolving a symbol in a shared library, * the symbols in the shared library are put ahead of the global symbol scope. * example-> When you load the ???.so, it has it's own request for the symbol. * Because you use RTLD_DEEPBIND this definition is looked up in the dependencies of this library first, * before looking in the main executable. */ __CleanupLibClose void* m_handle = dlopen(libName, RTLD_DEEPBIND | RTLD_NOW | RTLD_LOCAL); if (!m_handle) { throw std::runtime_error(dlerror()); } if(factoryFuncName!=NULL){ if (!(libraryObject.factoryObject.dlsym = dlsym(m_handle, factoryFuncName))) { throw std::runtime_error(dlerror()); } } if(destroyFuncName!=NULL){ if (!(libraryObject.destroyObject.dlsym = dlsym(m_handle, destroyFuncName))) { throw std::runtime_error(dlerror()); } } *pClassInterface =(*libraryObject.factoryObject.factoryMethod)(); } template<class CInterfacePtr> bool destroy(CInterfacePtr** pClassInterface) { return libraryObject.destroyObject.destoryMethod(*pClassInterface); } private: PluginLoader(const PluginLoader&); PluginLoader& operator=(const PluginLoader&); }; /* this class is invoke strategy shared library wrapper * template arg1: reference interface class */ template<class InterfacePtr> class Solver { public: Solver(){}; Solver(cBytes cLibName, cBytes cFactoryFuncName ,cBytes cDestroyFuncName=NULL) :m_interfacePtr(NULL){ m_pluginLoader(cLibName, cFactoryFuncName, &m_interfacePtr ,cDestroyFuncName); } virtual ~Solver(){ m_pluginLoader.destroy(&m_interfacePtr); DELOBJ(m_interfacePtr); } // important: this pure virtual method must be implemented in derived class. virtual void solve() =0; protected: template<class CInterfacePtr> inline void getInterface(CInterfacePtr& inputInterFace){ if(m_interfacePtr!=NULL){ inputInterFace = m_interfacePtr; } } private: //shared library interface class member. InterfacePtr m_interfacePtr; //instance of plugin loader class. PluginLoader<InterfacePtr> m_pluginLoader; }; /*proxy class shared library. this class is immutable type * class type: pointer type of shared library interface class. * template arg1 : encrypt interface class pointer * template arg2 : string stream reference pointer * */ template<class InterfacePtr ,typename InputType> class EncryptLibraryLoader : public Solver<InterfacePtr>{ protected: public: // arg1 : shared library name. // arg2 : reference factory method name in shared library. // arg3 : reference destroy method name in shared library. // arg4 : output string stream EncryptLibraryLoader(InputType outStream ,cBytes cLibName, cBytes cFactoryFuncName ,cBytes cDestroyFuncName=NULL) : Solver<InterfacePtr>(cLibName,cFactoryFuncName,cDestroyFuncName) , m_outStream(outStream) { /* important: must be call getInterface in super class and get * interface class reference and copy in member pointer in this class. */ getInterface(m_interfacePtr); } virtual ~EncryptLibraryLoader() { //clean up member pointer DELOBJ(m_interfacePtr); DELOBJ(m_outStream); } /* get the byte stream from encrypt logic.ini file. * arg1 : reference bytes stream. * return type : reference stream pointer * * important: must be call getInterface in super class and get * interface class reference and copy in member pointer in this class. * */ inline void solve(){ if(m_outStream!=NULL){ try { if (m_interfacePtr!=NULL) { m_interfacePtr->setIoType(C_LOWLEVEL); m_interfacePtr->getDecBuffer(m_outStream,const_cast<char*> (LogicFileName)); } //important : if interfacePtr is loaded. // this method dispossess member static pointer in memory section of library. m_interfacePtr->dispose(0); } catch (std::runtime_error& e) { printf("%s \n", e.what()); } } } private: //EncryptLibraryLoader(); EncryptLibraryLoader(const EncryptLibraryLoader&); EncryptLibraryLoader& operator=(const EncryptLibraryLoader&); //shared library interface class member. InterfacePtr m_interfacePtr; InputType m_outStream; }; /*proxy class SclVoter library. this class is immutable type * class type: pointer type of shared library interface class. * template arg1 : SclVoter interface class pointer * template arg2 : Number of nodes with type int * */ template<class InterfacePtr,typename InputType> class SclVoterLibraryLoader : public Solver<InterfacePtr>{ protected: public: // arg1 : shared library name. // arg2 : reference factory method name in shared library. // arg3 : reference destroy method name in shared library. // arg4 : numbers of node explicit SclVoterLibraryLoader(InputType nNode ,cBytes cLibName, cBytes cFactoryFuncName, cBytes cDestroyFuncName=NULL) : Solver<InterfacePtr>(cLibName,cFactoryFuncName,cDestroyFuncName), m_x_nNode(nNode){ } virtual ~SclVoterLibraryLoader() { //clean up member pointer DELOBJ(m_interfacePtr); } /* initializing SCLVoter */ inline void solve(){ /* important: must be call getInterface in super class and get * interface class reference and copy in member pointer in this class. */ getInterface(m_interfacePtr); if(m_interfacePtr!=NULL){ char strConfigPath[100]; copy(strConfigPath,m_x_nNode); if(!m_interfacePtr->Init(strConfigPath)) { printf("Error initializing SCLVoter (file %s) !\n",strConfigPath); } } } private: SclVoterLibraryLoader(); SclVoterLibraryLoader(const SclVoterLibraryLoader&); SclVoterLibraryLoader& operator=(const SclVoterLibraryLoader&); //shared library interface class member. InterfacePtr m_interfacePtr; InputType m_x_nNode; }; #endif /* PLUGINLOADER_H_ */ و در این مرحله به استفاده از آبجکت های زیر از کتابخانه های خود استفاده نمایید. std::istringstream* file=NULL ; { Solver<encAbstractPtr> *loader = new EncryptLibraryLoader<encAbstractPtr,std::istringstream**> ( &file ,LibEncryptorName, LibFactoryMethod , LibDestyoryMethod); // initial encryption library. loader->solve(); loader=NULL; } Solver<ICLAbstractPtr> *loader = new SclVoterLibraryLoader<ICLAbstractPtr,int> ( m_nNodeId ,SCLVOTER_SO_PATH, SCLVOTER_GET_INSTANCE_FUNCTION_NAME ); if(pSCLVoterManager == NULL) { return false; } // initial SCLvoter. loader->solve(); loader=NULL; در صورتی که نیاز به استفاده از کتابخانه در ویژوال سی ++ بود در همین تاپیک اعلام کنید تا انجام بدم.
  2. فرهاد شیری

    تجمیع و ترکیب که ماهیتا خیلی باهم تفاوت دارند! اگر بخواهم خیلی ساده توضیح بدم برای اینکه در زبان مدلسازی بخواهید تجمیع را درک کنید مثال بارز و پرکاربردش در محیط کدنویسی میشه containers مثل vector , map , list ,stack , queue ,dequeue که داده هایی که در داخل این ظرفها نگه داری میکنند یک نوع از تجمیع را در مدل class diagram نمایش میده. و برای نوع ترکیب هم مثال پرکاربردش در محیط کد نویسی ، میشه به تعریف یک داده عضو در یک کلاس با جنس و نوعی از یک شی دیگر را اشاره کنم در حقیقت اشاره صریح به has-a در پلی مورفیسم داره! که در زبان مدل سازی هر کدوم را با یک نوع فلش(علامت) خاص نمایش میدهند. شاید نشه! خیلی قاطعانه جواب این سوال را داد چون به خیلی عوامل بستگی داره! ولی کلا در مهندسی نرم افزار همیشه توصیه میشه که بجای استفاده از وراثت از ترکیب استفاده کنید در برنامه ها! اونهم به خیلی دلایل که توضیحاتش توی نت زیاد هست . و همینطور استفاده از containers در برنامه نویسی یک امر اجتناب ناپذیر هست البته استفاده از این تکنیکها شاید تاثیر مستقیمی بر روی کیفیت یک نرم افزار نداشته باشه! ولی براساس تکنیکهای مهندسی نرم افزار و تکنیکهای SOLID Programming استفاد از این روشها بدون شک در ایجاد یک نرم افزار با کیفیت تر که هم Functionality , Usability ,Reliability ,Performance , Supportability را رعایت کرده باشند مطمئنا نقش بسزایی خواهند داشت.
  3. کلاس SingleTone سازگار با کامپایل VisualC++14 #pragma once #include <memory> template<class T> class SingleTone { private: SingleTone() = default; inline ~SingleTone() { destory(m_instance); }; public: SingleTone(const SingleTone&) = delete; //copy ctor SingleTone(SingleTone&&) = delete; //move ctor SingleTone& operator=(const SingleTone&) = delete; // copy oprator assignment SingleTone& operator=(SingleTone&&) = delete; // move oprator assignment static void destory(T* my) { delete my; } static std::unique_ptr<T ,decltype(&destory)>& getUniquePInstance() { static T* m_instance = new T; return std::unique_ptr<T, decltype(&destory)>(std::reference_wrapper<T*>(m_instance), &destory); } };
  4. احسنت! درود بر این نطق زیبا! تصور کنید که کسی که به ادعای خودش ارشد رشته برق هست چرا باید بیاد آموزش سی و سی پلاس پلاس و جاوا و چند تا زبان دیگه را یاد بده! مگر چند تا واحد برنامه نویسی پاس کردند تو دانشکده فنی برق که حالا در خودش این توانایی را می بینه! بعد خیلی جالبه! اگر یک مهندس نرم افزار بیاد بخواهد تو کار یک مهندس برق و الکترونیک دخالت کنه و آموزش تهیه کنه مثلا برای برنامه های Hard Code در صنعت برق و قدرت و الکترونیک را عرض میکنم، شک نکنید یک دقیقه تحمل نمیکنن و زمین و زمان رو بهم وصل میکنن که چرا شما تو کار ما دخالت میکنید بعد همون طرف میاد برای سی آموزش میذاره ده تا اسلاید درست میکنه عنوانش هم میذاره آموزش حرفه ای زبان سی!!! پس نتیجه میگیریم که اغلب افرادی که در حوزه فنی خودشون هیچ فایده ای ندارند به فکر آب گل آلود این صنعت بی قانون نرم افزار کشورمون رو میارن طرف میشینه تو خونه اش چهارتا ویدئو بی کیفیت رکورد میکنه یکسری سایت های سودجوی وطنی هم میان پخشش میکنن و یکسری هم جوان تازه کار میرن این آموزش ها را تهیه میکنن خوب حالا سوال اصلی اینجاست در این چرخه آموزش مجازی چه کسانی سود می برند؟ وبه چه قیمتی ؟ پس این صحبت جناب اسدزاده کاملا شفاف می شود که واقعا نبود یک شورای صنفی حرفه ای در این حوزه برای نظارت بر روی این موارد خیلی خیلی لازم و ضروری شده تا حداقل جلوی سودجویی بعضی از این افراد که در هر رشته ای غیر مرتبط که برای صنعت نرم افزار که بسیار هم فنی و پیچیده است، آکادمی آموزش مجازی راه اندازی میکنه، گرفته بشه.
  5. جناب اسدزاده تشکر بابت این نظرسنجی خوب! لازم دیدم تجربه خودم را درباره این مطلب در اینجا منتشر کنم امید که مفید فایده واقع شود. متاسفانه در سالهای اخیر با اینکه صنعت نرم افزاری کشور رشد خوب و چشمگیری داشته ولی متاسفانه عدم فرهنگ سازی های مناسب در این زمینه باعث شده افراد با سابقه طولانی در این صنعت با مشکلات جدی روبه رو شوند. به طوریکه افرادی که در سالهای اخیر وارد این حوزه می شوند و تحصیلات اکادمیک را بعضا مرتبط و با عرض تاسف بعضا غیر مرتبط می گذارنند بعد از ورود به این بازار به علت اینکه اکثر این افراد سطح آموزش های بی کیفیت را تجربه کرده اند به این ترتیب اعتماد به نفس خیلی پایینی دارند با درآمدهای حتی پایینتر از حقوق وزارت کار راضی به کار می شوند به این علت که تصور این افراد این هست که چند سال به این روش تجربه ی بیشتری بدست می آورند و از آنجایی هم که اکثر شرکت های معتبر نرم افزاری حداقل در تهران را عرض میکنم بدنبال این نیروها هستند به این علت که هم هزینه ای خیلی کمتری میکنند و هم طرف را مجبور به یاد گرفتن میکنند تا بتونن کار خودشون را هرچند اشتباه و پر از ایراد انجام دهند. وبا این کار به افرادی که سالها تجربه دارند بیش از پیش لطمه خواهند زد. چرا که اصولا در شرکتهای معتبر نرم افزاری علی الخصوص در سالهای اخیر انقدر سطح مدیریت به سمت درآمد بیشتر سوق پیدا کرده که این شرکتها کلا برای افراد با تجربه ی این حوزه کمتر ارزش قائل هستند. سند این حرف بنده هم آگهی های این شرکتها ست با کمی دقت می توانید مشاهده کنید برخی از این شرکتها در تمام ایام سال در حال جذب نیرو هستند(البته فقط شرکتهای معتبر را عرض میکنم) که این مطلب نشان دهنده این واقعیت هست که افرادی که استخدام میکنند توانایی لازم را ندارند و بعد از چندماه شرکت را ترک میکنند ویا صرفا پروژه ای تعریف شده و بعد از اتمام عذر برنامه نویس را خواستند. و نکته جالبتر این هست که در سالهای اخیر آگهی های استخدامی به نام مهندس نرم افزار ویا معمار نرم افزار خیلی کم شده یا بهتر بگم دیگه نا پیدا شده! واگر هم یک نیروی باتجربه با یک رزومه قوی در خواست حقوق 7-8 میلیون را ازشون داشته باشه انگار به تمام مقدسات این شرکتها توهین شده! بنابراین ای کاش کسانی که می خواهند وارد این صنعت شوند به توانایی های خودشون کاملا شناخت پیدا کنند و صرفا بخاطر اسم این صنعت وارد این بخش نشوند که مجبور باشند در مقطع ارشد دنبال کسی باشند که براشون پروژه انجام بده! یا حداقل در صورتی که وارد این حوزه شدند کمی به پرستیژ و مدرک این رشته احترام بگذارند و با حقوق های زیر یک میلیون مشغول به کار نشوند! تا بلکه به این طریق شرکت هایی هم که در این حوزه هستند حساب کار بیش از پیش دستشون بیاد. در حوزه وب و موبایل هم که الی ماشاالله از هر 10 برنامه نویس 11 تا یا برنامه نویس حرفه ای اندروید هستند ویا ادعا پیغمبری در حوزه وب دارند پس بنابراین وضعیت اسفناک فریلنسینگ هم که دیگه جای خودش را داره! سوالی که همیشه برای خودم مطرح بوده این بوده که چطور یکنفر می تونه یک اپلیکیشنی که با یک سناریو مهندسی شده حداقل 3 ماه وقت لازم داره و با هزینه های جاری روزانه برنامه نویس حداقل بین 12 تا 15 میلیون هست! را میاد پیشنهاد میده 2 میلیون اونهم تا 10 روز کاری!!! کافی یه سر به سایت های فریلنسینگ خارجی بزنید هزینه های پروژه ها از 500 دلار شروع میشه حتی برای یک تغییر ساده در وورد پرس ! پس بازهم به همون مطلب میرسیم که عدم شناخت کافی از توانایی های خود و وارد شدن به یک حوزه کاملا حرفه ای بدون شناخت کامل و تحت آموزش قرار گرفتن های سطح پایین و غیر کاربردی دانشگاه باعث شده افرادی به این حوزه وارد شوند، که نه تنها کمکی به این صنعت نمیکنند بلکه برای حرفه ای های این صنعت هم چالش ایجاد کرده اند. البته بحث راجع به این مقوله خیلی زیاده که خودش به تنهایی یک کتاب 500 صفحه ای میشه به همین علت چیکده ای از تجربیات خودم را عرض کردم.
  6. فرهاد شیری

    البته در بعضی شرایط شاید بهتر باشه بعضی از این توابع را خودتون باز نویسی کنید در شرایط خاص نرم افزاری ، اما در اکثر مواقع خیر بهتره از همین استاندارد ها استفاده کنید. اونهم به این علت که احتمال خطا خیلی کمتر هست یا نزدیک به صفر هست چون این توابع در شرایط مختلف تست شده اند تبدیل به استاندارد شده اند اون هم نه توسط یک نفر بلکه توسط یک تیم چند صد نفری ... دقیقا همین اتفاق می افتد منتهی نه در خروجی کامپایل شما بلکه در زمان تبدیل به کد ماشین توسط خود کامپایلر و لینکر این انعقاد انجام می شود و خروجی باینری شما ترکیبی از کد های کامپایل شده شما خواهد بود به اضافه کلاسها و توابع استاندارد ++C که شما در برنامه خود استفاده کرده اید، به صورت پویا به کد ماشین برنامه شما پیوند زده می شود. پس ماکروهایی هم که در هدر های استاندارد مشاهده میکنید در زمان کامپایل تاثیر گذار هستند ولی در حجم باینری فایل خروجی یا تاثیر خیلی کمی دارند ویا اصلا تاثیری نخواهند داشت. معمولا هم به همین دلیل توصیه میشود که مثلا بجای استفاده از دستور using namespace std دقیقا به تابعی که لازم دارید اشاره کنید std::cout دراین روش در خروجی باینری فایل تاثیر گذار خواهد بود. پیشنهاد میکنم این لینکها را هم مطالعه کنید. فرق بین کامپایل استاتیک و داینامیک
  7. فرهاد شیری

    تمام برنامه ها در زمان شروع در یک نخ به نام Main Thread اجرا می شوند. نخ های ایجاد شده توسط برنامه درسطح کاربر هستند. اصولا نخ ها در دو سطح کاربر و سطح هسته ایجاد می شوند. که هر پلت فرم برنامه نویسی هم برای خود از یک تکنولوژی برای مدیریت نخ ها استفاده میکند . برای اطلاعات بیشتر می تونید مباحث آپارتمان نخ ها و STA single thread apartement رامطالعه کنید. بنابراین وقتی که یک نخ اصلی برنامه اجرا می شود توسط سیستم عامل عملیات Timing , priority , state,... کنترل می شود و اینکه شما بتونید برنامه ای بنویسید که از تمام هسته های پردازشگر در جهت اجرای بهتر برنامه خود استفاده نمایید باید برنامه شما قابلیت موازی کردن عملیات ها ویا همزمانی پروسه هارا داشته باشد در این صورت شما با استفاده از کتابخانه های همزمانی می توانید در زمان ایجاد حوضچه های نخ Thread Pool نحوه استفاده از هسته ها را برای این حوضچه ها تعریف کنید که مثال بتوانند از تمام هسته ها به طوری که هسته های دیگر در اجرای وظایف خود دچار اختلال نشوند، اجرا شوند. مثلا تصور کنید یک مجموعه از داده عددی را می خواهید سورت کنید همانطور که می بینید با استفاه از حوضچه های نخ می توانید به صورت موازی عملیات هر بخش را دریک نخ اجرا کنید و خروجی هر نخ را با نخ های دیگه ادغام کنید تا در نهایت کل مجموعه مرتب شود. procedureparallelmergesort(id, n, data, newdata) begin data = sequentialmergesort(data) for dim = 1 to n data = parallelmerge(id, dim, data) endfor newdata = data end البته این الگوریتم اجرا برای شما نمایش میده! و از آنجائیکه نوشتن برنامه های موازی کار بسیار پیچیده ای می باشد و معمولا به تجربه ای زیاد نیاز دارید بهتر است از کتابخانه های موازی سازی که خیلی بهینه این قبیل موازی سازی را برای شما انجام می دهند استفاده نمایید
  8. فرهاد شیری

    البته در تکمیل فرمایش جناب اسدزاده! بله در واقع تفاوت Class و Struct در زبان ++C مربوط به همین دسترسی به خصیصه های پیش فرض تعریف شده است. اما اغلب برنامه نویسانی که از زبان C به ++C مهاجرت کرده اند معمولا برای مدل کردن داده های خود از struct استفاده میکند چون ضمن خوانایی بیشتر از نظر مفهومی هم خیلی بهتر هست و البته شاید یک دلیل هم اینکه از struct استفاده میکنیم برای این هست که وقتی شما می خواهید داده های تودرتو با struct و union ایجاد کنید، مطمنا تعریف struct بسیار ملموس تر و قابل فهم تر از استفاده از تعریف class می باشد مثل کد زیر... static struct ITEM_STRUCT{ char*strName; int nCmdLen; int nIndLen; union stUnion { int ix; int iy; struct iS { char * isC; int isZ; } } stU1,stU2 ; int getIndLen(int ItemType) { if (ItemType != INT_ACK) return nIndLen; else { if(gbGenerateAx) return nIndLen+1; else return nIndLen; } } }
  9. فرهاد شیری

    با تشکر از نکاتی که دوست عزیز قاسم رمضانی منش زحمت کشیدند واینجا قرار دادند. معمولا وقتی کلاس را به صورت ژنریک با استفاده از template تعریف میکنیم باید پیاده سازی های کلاس هم به صورت inline تعریف شوند و البته از قوانین تعریف متدهای inline (مبنی بر اینکه دستورات متد نباید بیشتر از چند خط باشد) نباید تخطی نمایید. ودر صورتی که دستورات زیادی باید پیاده شوند در متدها حتما باید این متدها به ماژولهای کوچکتر تقسیم شوند و یا از روشهای وراثت و پلی مورفیسم در تعاریف استفاده شود. و علت این قضیه هم کاملا مشخص است همانطور که دوست عزیز جناب آقای رمضانی منش هم اشاره کردند وقتی خود کامپایلر این جداسازی را انجام می دهد دلیلی برای انجام این کار وجود ندارد. به عنوان مثال... #if COMPILER == COMPILER_MSVC # define INLINE inline # define FORCE_INLINE __forceinline #elif COMPILER == COMPILER_GNUC # define INLINE inline # define FORCE_INLINE inline __attribute__((always_inline)) #elif COMPILER == COMPILER_CLANG || COMPILER == COMPILER_APPLECLANG # define INLINE inline # define FORCE_INLINE inline __attribute__((always_inline)) #else # define INLINE inline # define FORCE_INLINE inline // no force inline for other platforms possible #endif template<typename Class_Type, typename...Ctor_Args, std::size_t... Arg_Count> struct invoker<ctor_type, as_object, type_list<Class_Type, Ctor_Args...>, index_sequence<Arg_Count...>> { using return_type = Class_Type; template<typename... TArgs> static INLINE variant invoke(TArgs&&...args) { if (check_all_true(args. template is_type<Ctor_Args>()...)) return variant(Class_Type(args. template get_value<Ctor_Args>()...)); else return variant(); } };
  10. فرهاد شیری

    تشکر عالی! مثل همیشه!
  11. تشکر! بابت ترجمه روان و مختصر مفیدی که بابت این تغییرات جدید قرار دادید.
  12. همواره یکی از چالش بر انگیزترین مباحث در دنیای نرم افزار حفاظت از داده های حساس برنامه ها می باشد. البته امروزه با کتابخانه ها و الگوریتم های رمزنگاری موجود در این صنعت کمی از عذاب آورترین چالش های مهندسین نرم افزار کمتر شده است، ولی به هرحال تمامی این روشها جدایی از بحث انعطاف پذیری و اطمینان از صحت اجرای الگوریتم توانایی اجرا در همه سکوها را ندارند. با این مقدمه کوتاه به بحث پر چالش ترین زبان برنامه نویسی جاوا و البته سیستم عامل معروف اندروید تحت این سکو می پردازیم، همانطور که می دانید حفاظت از داده های حساس در اندروید به علت متن باز بودن سکوی خود می تواند یکی از پر چالش ترین بحث های برنامه نویسی باشد. به همین علت کتابخانه ها و روش های زیادی وجود دارند تا از این اطلاعات حساس نگهداری نمایید. البته در این مقاله بحث بر سرحفاظت از اطلاعات حساس در زمان اجرای اپ های موبایل می باشد مانند کلمات عبور و یا اطلاعات حساس استفاده شده در وب سرویس ها در زمان ارسال پکت ها به سرور می باشد. بنابراین در اینجا کاری با قسمت پایگاه داده و روش های برنامه نویسی سوکت و مباحث دیگر نخواهیم داشت. در زبان جاوای گوگل که برای سیستم عامل اندروید توسعه داده شده است ابزار قدرتمندی به نام Java Native Interface طراحی شده است که می تواند یک رابط بومی باشد برای استفاده از کیت هایی که به زبان ++C , C توسعه داده شده اند به نام Native Development Kit که با استفاده از این ابزار و برخی از ابزار های دیگر مانند ,Make ,LLDB,Clang... این امکان را خواهید داشت تا کمبود هایی که در زبان جاوا وجود دارد را با استفاده از برنامه نویسی سی و سی پلاس پلاس ، جبران نمایید. معمولا یکی از پرکاربرد ترین این برنامه ها نوشتن الگوریتم های اختصاصی رمزنگاری می باشد. به این علت که سورسهای زبان جاوا به راحتی با استفاده از تکنیک های مهندسی معکوس استخراج می شوند، به همین علت تهیه چنین الگوریتم هایی در نرم افزار های موبایل حیاتی می باشد. و البته توجه داشته باشید که می توانید از کتابخانه های آماده هم استفاده نمایید حتی سمت زبان سی پلاس پلاس ولی به هرحال اختصاصی نوشتن اینچنین الگوریتم هایی هم خالی از لطف و تجربه نخواهد بود در عین حال هم بلکه پیچیده تر از الگوریتم های آن کتابخانه باشد که بدین ترتیب روش های مهندسی معکوس را هم بسیار سخت تر خواهد کرد ویا عملا غیر ممکن خواهد شد. وبا توجه به اینکه برنامه هایی که با زبان سی و سی پلاس پلاس که نوشته می شوند مستقیم به اسمبلی تفسیر و سپس به زبان ماشین تبدیل می شوند عملا دی کامپایلر ها توانایی فهمیدن درست سورس کدها را نخواهند داشت وفقط می توانند به کد های اسمبلی که البته خیلی پیچیده تر از کد اصلی برنامه هست تبدیل نمایند. اکنون پس از این توضیحات کوتاه در زیر سورس کدهای برنامه ای درهم سازی را که از تلفیق چند روش رمزنگاری در اندروید برای استفاده سمت جاوا ی اندرید نوشته ام را خدمت شما ارسال میکنم. توضیحاتی راجع به الگوریتم ها فعلا نمیدم اگر از دوستان علاقمند بودند در همین بخش اعلام کنند تا توضیح عملکرد را خدمتتان ارائه کنم. برای استفاده باید ابزار های زیر داشته باشید JDK1.8 , JRE , Android Studio , NDK rb17 , CMAKE ,LLDB ,Android Build Tools کلاس native_utils.h #ifndef BODYPOWER_NATIVE_UTILS_H #define BODYPOWER_NATIVE_UTILS_H #include <android/log.h> #include <iomanip> #include <locale> #include <sstream> #include <memory> #define TAG_LOG_ANDROID "NativeTagLog" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG_LOG_ANDROID,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG_LOG_ANDROID,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG_LOG_ANDROID,__VA_ARGS__) using namespace std; namespace BodyPowerNative { struct Exp : public exception { const char* ExceptionDefualtMsg = "error by this exception -> %s"; public: Exp() = default; Exp(const Exp &) = default; virtual ~Exp() = default; static void destory(Exp *my) { delete my; } static unique_ptr<Exp, decltype(&destory)> instance() { return unique_ptr<Exp, decltype(&destory)>(new Exp(), &destory); } static Exp getInstance() { return Exp(); } const char* what() const noexcept override { return exception::what(); } void printStackTrace(const char *cValue) const { LOGE(ExceptionDefualtMsg, cValue); }; }; class Native_Utils { public: Native_Utils() = default; template<typename T> static string NumberToString(T Number) { ostringstream ss; ss << Number; return ss.str(); } template<typename T> static T StringToNumber(const string &Text) { istringstream ss(Text); T result; return ss >> result ? result : 0; } }; typedef Native_Utils NU; } #endif //BODYPOWER_NATIVE_UTILS_H فایل JniByteArrayWrapper.h #ifndef BODYPOWER_JNIBYTEARRAYWRAPPER_H #define BODYPOWER_JNIBYTEARRAYWRAPPER_H #include <jni.h> #include <memory> #include <algorithm> #define SHA512_BLOCK_SIZE 0x7A #define SHA512_ENDBYTE_BIGCAPS 0x5A #define SHA512_MASK 0x5B #define SHA512_STARTBYTE_CODESMALL_CAPS 0x61 #define SHA512_STARTBYTE_CODEBIG_CAPS 0x41 #define SHA512_STARTBYTECODE_NUMERIC 0x30 #define SHA512_ENDBYTE_CODE_NUMERIC 0x39 #define SHA512_START_DIGEST_BYTECODE_SMALLCAPS 0x60 #define SHA512_START_DIGEST_BYTECODE_BIGCAPS 0x40 #define SHA512_LEFT_SIDESHIFT 0xF #define SHA512_SPACE_CHARBYTE 0x1B #define PARAM_LENGTH 0xB using namespace std; namespace BodyPowerNative { class JniByteArrayWrapper { private: u_long _key = 0; u_long _sKeyLength = 0; string _stringKey; jsize _dataLength; jsize _lenHashData; jbyteArray _jb_u; JNIEnv *_jniEnv; vector<char> vectorBytes; public: JniByteArrayWrapper() = default; // default ctor JniByteArrayWrapper(JNIEnv *&, jbyteArray); //default ctor JniByteArrayWrapper(const JniByteArrayWrapper &); // copy ctor void const parseJByteArray(); virtual ~JniByteArrayWrapper(); bool operator==(const JniByteArrayWrapper &rhs) const; // equal operator overload bool operator=(const JniByteArrayWrapper &rhs) const; // assignment operator overload bool operator!=(const JniByteArrayWrapper &rhs) const; // not equal operator overload const jbyteArray getJBytes() const; const JNIEnv &getEnv() const; u_long get_key() const; u_long get_sKeyLength() const; const string &get_stringKey() const; jsize get_dataLength() const; jsize get_lenHashData() const; const vector<char> &getVectorBytes() const; void encodingNum(); }; typedef JniByteArrayWrapper jByteArrayW; } #endif //BODYPOWER_JNIBYTEARRAYWRAPPER_H فایل JniByteArrayWrapper.cpp #include "JniByteArrayWrapper.h" #include "Native_Utils.h" using namespace BodyPowerNative; JniByteArrayWrapper::JniByteArrayWrapper(const JniByteArrayWrapper &rhs) { _jb_u = rhs._jb_u; _jniEnv = rhs._jniEnv; } JniByteArrayWrapper::~JniByteArrayWrapper() { //delete[]_hash_str; vectorBytes.clear(); } bool jByteArrayW::operator=(const JniByteArrayWrapper &rhs) const { return false; } bool jByteArrayW::operator==(const JniByteArrayWrapper &rhs) const { return _jb_u == rhs._jb_u; } bool jByteArrayW::operator!=(const JniByteArrayWrapper &rhs) const { return rhs._jb_u != _jb_u; } const jbyteArray jByteArrayW::getJBytes() const { try{ jbyteArray _encryptBytes = _jniEnv->NewByteArray(_lenHashData); char *_hash_str = new char(_lenHashData); transform(vectorBytes.begin(), vectorBytes.end(), _hash_str, [&](char itByte) { return itByte; }); _jniEnv->SetByteArrayRegion(_encryptBytes, 0, _lenHashData, reinterpret_cast<const jbyte *>(_hash_str)); delete _hash_str; return _encryptBytes; } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } return 0; } const JNIEnv &jByteArrayW::getEnv() const { return *(_jniEnv); } void const jByteArrayW::parseJByteArray() { try{ unique_ptr<jbyte> _readByte = make_unique<jbyte>(); _dataLength = _jniEnv->GetArrayLength(_jb_u); for (u_int i = 0; i < _dataLength; ++i) { _jniEnv->GetByteArrayRegion(_jb_u, i, 1, _readByte.get()); vectorBytes.push_back(*(_readByte.get())); } _lenHashData = _dataLength ; } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } } void jByteArrayW::encodingNum() { try { string strKey = get_stringKey(); for (string::iterator _keyIter = strKey.begin(); _keyIter != strKey.end(); ++_keyIter) { if (*(_keyIter) >= SHA512_STARTBYTECODE_NUMERIC && *(_keyIter) <= SHA512_ENDBYTE_CODE_NUMERIC) { char shiftNum = static_cast<char>(*(_keyIter) + SHA512_LEFT_SIDESHIFT); vectorBytes.push_back(shiftNum); } } } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } } u_long jByteArrayW::get_key() const { return _key; } u_long jByteArrayW::get_sKeyLength() const { return _sKeyLength; } const string& jByteArrayW::get_stringKey() const { return _stringKey; } jsize jByteArrayW::get_dataLength() const { return _dataLength; } jsize jByteArrayW::get_lenHashData() const { return _lenHashData; } const vector<char> &JniByteArrayWrapper::getVectorBytes() const { return vectorBytes; } JniByteArrayWrapper::JniByteArrayWrapper(JNIEnv *&env, jbyteArray jb) : _jb_u(jb), _jniEnv(env) {} فایل ParseEncryptAlgol.h #ifndef BODYPOWER_PARSEENCYRPTALGOL_H #define BODYPOWER_PARSEENCYRPTALGOL_H #include <sys/types.h> namespace BodyPowerNative { class JniByteArrayWrapper; class ParseEncryptAlgol { private: u_int num_counter = 0; int _extractKeyNum = 0; int nShift = 0; char digest = 0; int *_splitKeyNumArrays; JniByteArrayWrapper*& _jniByteArrayWrapper; public: ParseEncryptAlgol(JniByteArrayWrapper*&); char evalAlgol(char byte); virtual ~ParseEncryptAlgol(); }; } #endif //BODYPOWER_PARSEENCYRPTALGOL_H فایل ParseEncryptAlgol.cpp #include "ParseEncryptAlgol.h" #include "JniByteArrayWrapper.h" using namespace BodyPowerNative ; ParseEncryptAlgol::ParseEncryptAlgol(JniByteArrayWrapper*& jniByteArrayWrapper) : _jniByteArrayWrapper(jniByteArrayWrapper) { _splitKeyNumArrays = new int[jniByteArrayWrapper->get_sKeyLength()]; } ParseEncryptAlgol::~ParseEncryptAlgol() { delete[]_splitKeyNumArrays; } char ParseEncryptAlgol::evalAlgol(char _readByte) { { if (num_counter < _jniByteArrayWrapper->get_sKeyLength()) { _extractKeyNum = _splitKeyNumArrays[num_counter++]; } else { num_counter = 0; _extractKeyNum = _splitKeyNumArrays[num_counter++]; } if (_readByte >= SHA512_STARTBYTECODE_NUMERIC && _readByte <= SHA512_ENDBYTE_CODE_NUMERIC) { return 0 ;// security::encodingNum(_readByte); } else if (_readByte + _extractKeyNum > SHA512_BLOCK_SIZE) { //z 122 nShift = _extractKeyNum > (SHA512_BLOCK_SIZE - _readByte) ? _extractKeyNum - (SHA512_BLOCK_SIZE - _readByte) : (SHA512_BLOCK_SIZE - _readByte) - _extractKeyNum; digest = static_cast<char>(SHA512_START_DIGEST_BYTECODE_SMALLCAPS + nShift); return digest; } else if (_readByte + _extractKeyNum > SHA512_ENDBYTE_BIGCAPS && _readByte <= SHA512_ENDBYTE_BIGCAPS) { //Z 90 nShift = _extractKeyNum > (SHA512_ENDBYTE_BIGCAPS - _readByte) ? _extractKeyNum - (SHA512_ENDBYTE_BIGCAPS - _readByte) : (SHA512_ENDBYTE_BIGCAPS - _readByte) - _extractKeyNum; digest = static_cast<char>(SHA512_START_DIGEST_BYTECODE_BIGCAPS + nShift); return digest; } else { return static_cast<char>(_readByte + _extractKeyNum); } } } فایل security.h #ifndef BODYPOWER_SECURITY_H #define BODYPOWER_SECURITY_H #include <jni.h> #include <string.h> #include <memory> #include "Native_Utils.h" #define Java_App_Class "com/nativeDb/materialDesign/MyApplication" namespace BodyPowerNative { class JniByteArrayWrapper; const char *BASE_URL = "--/"; const char *BODY_POWER_API_SOURCE_REF = "phpSource/"; const char *COACH_PHOTO_BASE_URL = "CoachPhoto/"; const char *SUPP_PHOTO_BASE_URL = "SuppImages/"; const char *COACH_DATA_BASE_URL = "getItems"; const char *COACH_DATA_BASE_URL_FAILD = "getItemsFaild"; const char *PROFILE_SEND_BASE_URL = "FetchProfileRow"; const char *PHOTO_PROFILE_SEND_BASE_URL = "uploadPhoto"; const char *REGISTER_USER_BASE_URL = "updateUser"; const char *EXIST_USER_BASE_URL = "checkExistUser"; const char *UPD_URL = "updateMentorList"; const char *SUPP_PROD_URL = "getItems_supp"; static u_int posSepChar =0 ; typedef unsigned int sha2_32t; typedef unsigned long sha2_64t; typedef jsize sha1_32t; typedef jbyte sha1_8; typedef struct sha512 { public: //unsigned bitMask :1; char *hash_str; char *hash_out = nullptr; inline sha512(sha1_32t lenHashData) { hash_str = new char[lenHashData]; if(!hash_str) throw Exp::getInstance(); } inline sha512(const sha512& rhs){ hash_str = new char[strlen(rhs.hash_str)]; if(!hash_str) throw Exp::getInstance(); this->hash_str = rhs.hash_str; if(hash_out != nullptr){ this->hash_out = rhs.hash_out; } } inline ~sha512() { delete[]hash_str; hash_str=nullptr; if(hash_out != nullptr) { delete[]hash_out; hash_out= nullptr; } } inline sha512& operator=(const sha512& rhs){ if(&rhs != this){ delete[]hash_str; this->hash_str = rhs.hash_str; if(hash_out != nullptr){ delete[]hash_out; this->hash_out = rhs.hash_out; } } return *this; } } sha512_ctx; class security { public: security() = default; ~security(){}; static jbyteArray encryptAlgol( JNIEnv *, jobject , jbyteArray); static jbyteArray encrypt( JNIEnv *, jobject , jbyteArray); static jbyteArray decrypt( JNIEnv *, jobject , jbyteArray); static jint customRand( JNIEnv *env, jobject , jint , jint ); static jstring baseApiUrl( JNIEnv *, jobject ); static jstring mentorApiUrl( JNIEnv *, jobject ); static jstring mentorPhotoApiUrl( JNIEnv *, jobject ); static jstring suppPhotoApiUrl( JNIEnv *, jobject ); static jstring mentorDataApiUrl( JNIEnv *, jobject ); static jstring mentorDataFaildApiUrl( JNIEnv *, jobject ); static jstring profileDataApiUrl( JNIEnv *, jobject ); static jstring profilePhotoApiUrl( JNIEnv *, jobject ); static jstring registerUserApiUrl( JNIEnv *, jobject ); static jstring privacyUserApiUrl( JNIEnv *, jobject ); static jstring updateMentorApiUrl( JNIEnv *, jobject ); static jstring suppProdApiUrl( JNIEnv *, jobject ); static jobjectArray mapParamToStringArray (JNIEnv *, jobject); static void splitKeyNum(int *&, const string&); static char encodingNum(const jbyte *); static char encodingNum(const char); private: static void encodingNum(string, char *&, jsize); static char decodingNum(const jbyte *); static string decodingNum(JNIEnv *, const jbyteArray &); static u_int getEndReadBytePos(JNIEnv *, const jbyteArray &, jsize); static void revAlgol(JNIEnv *&, _jbyteArray *, JniByteArrayWrapper *&, char *&); static void revAlgol(JNIEnv *&, _jbyteArray *, JniByteArrayWrapper *&, char *&, jbyteArray &); }; typedef security SC; static JNINativeMethod method_table[] = { {"encrypt", "([B)[B", (void *) SC::encrypt}, {"decrypt", "([B)[B", (void *) SC::decrypt}, {"customRand", "(II)I", (void *) SC::customRand}, {"baseApiUrl", "()Ljava/lang/String;", (void *) SC::baseApiUrl}, {"mentorApiUrl", "()Ljava/lang/String;", (void *) SC::mentorApiUrl}, {"mentorPhotoApiUrl", "()Ljava/lang/String;", (void *) SC::mentorPhotoApiUrl}, {"mentorDataApiUrl", "()Ljava/lang/String;", (void *) SC::mentorDataApiUrl}, {"suppPhotoApiUrl", "()Ljava/lang/String;", (void *) SC::suppPhotoApiUrl}, {"mentorDataFaildApiUrl", "()Ljava/lang/String;", (void *) SC::mentorDataFaildApiUrl}, {"profileDataApiUrl", "()Ljava/lang/String;", (void *) SC::profileDataApiUrl}, {"profilePhotoApiUrl", "()Ljava/lang/String;", (void *) SC::profilePhotoApiUrl}, {"registerUserApiUrl", "()Ljava/lang/String;", (void *) SC::registerUserApiUrl}, {"privacyUserApiUrl", "()Ljava/lang/String;", (void *) SC::privacyUserApiUrl}, {"updateMentorApiUrl", "()Ljava/lang/String;", (void *) SC::updateMentorApiUrl}, {"suppProdApiUrl", "()Ljava/lang/String;", (void *) SC::suppProdApiUrl}, {"mapParamToStringArray", "()[Ljava/lang/String;", (void *) SC::mapParamToStringArray} }; extern "C" { jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) { return -1; } else { jclass clazz = env->FindClass(Java_App_Class); if (clazz) { env->RegisterNatives(clazz, method_table, sizeof(method_table) / sizeof(method_table[0])); env->DeleteLocalRef(clazz); return JNI_VERSION_1_6; } else { return -1; } } } } } #endif //BODYPOWER_SECURITY_H فایل security.cpp /* const char *str = (*env)->GetStringUTFChars(env, s, 0); (*env)->ReleaseStringUTFChars(env, s, str); */ //string _jskey = static_cast<ostringstream*>( &(ostringstream() << _key) )->str(); /* uint64_t features = android_getCpuFeatures(); if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) { //NEON is not available } else { //NEON is available } int android_getCpuCount(void); */ #include "security.h" #include "ParseEncryptAlgol.h" #include "JniByteArrayWrapper.h" #define sum32(x) (x += *(_readByte.operator->())) #define shift_r32(_ex_num, _read_byt) nShift = (_ex_num > (SHA512_BLOCK_SIZE - _read_byt) ? \ _ex_num - (SHA512_BLOCK_SIZE - _read_byt) : \ (SHA512_BLOCK_SIZE - _read_byt) - _ex_num) #define shift_l32(_ex_num, _read_byt) nShift = (_ex_num > (SHA512_ENDBYTE_BIGCAPS - _read_byt) ? \ _ex_num - (SHA512_ENDBYTE_BIGCAPS - _read_byt) : \ (SHA512_ENDBYTE_BIGCAPS - _read_byt) - _ex_num) #define compile_num(i) ctx->hash_str[i] = encodingNum(_readByte.operator->()); #define compile_wbuf97(i) ctx->hash_str[i] = static_cast<char>(SHA512_START_DIGEST_BYTECODE_SMALLCAPS + nShift); #define compile_wbuf65(i) ctx->hash_str[i] = static_cast<char>(SHA512_START_DIGEST_BYTECODE_BIGCAPS + nShift); #define compile_wbuf(i) ctx->hash_str[i] = static_cast<char>(*(_readByte.operator->()) + _extractKeyNum); #define compile_dec_wbuf27(i) ctx->hash_str[i] = static_cast<char>(SHA512_SPACE_CHARBYTE); #define compile_dec_num(i) ctx->hash_str[i] = decodingNum(_readByte.operator->()); #define compile_dec_wbuf65(i) ctx->hash_str[i] = static_cast<char>( SHA512_MASK - \ ((*(_readByte.operator->()) - SHA512_STARTBYTE_CODEBIG_CAPS) > _extractKeyNum ? \ (*(_readByte.operator->()) - SHA512_STARTBYTE_CODEBIG_CAPS) - _extractKeyNum : \ _extractKeyNum - (*(_readByte.operator->()) - SHA512_STARTBYTE_CODEBIG_CAPS)) ); #define compile_dec_wbuf65_2(i) ctx->hash_str[i] = static_cast<char>(SHA512_BLOCK_SIZE - (_extractKeyNum - \ (*(_readByte.operator->()) - SHA512_START_DIGEST_BYTECODE_SMALLCAPS))); #define compile_dec_wbuf97(i) ctx->hash_str[i] = static_cast<char>(nlShift); #define compile_dec_wbuf(i) ctx->hash_str[i] = static_cast<char>(*(_readByte.operator->()) - _extractKeyNum); using namespace BodyPowerNative; jbyteArray security::encryptAlgol(JNIEnv *env, jobject j, jbyteArray jb) { JniByteArrayWrapper *jniByteArrayWrapper = new JniByteArrayWrapper(env, jb); jniByteArrayWrapper->parseJByteArray(); jbyteArray _encryptBytes = env->NewByteArray(jniByteArrayWrapper->get_lenHashData()); char *hash_str = new char[jniByteArrayWrapper->get_lenHashData()]; vector<char> vect = jniByteArrayWrapper->getVectorBytes(); /* ParseEncryptAlgol* parseEncryptAlgol= new ParseEncryptAlgol(jniByteArrayWrapper); transform(vect.begin(), vect.end(), hash_str,[](char byte){ return parseEncryptAlgol->evalAlgol(byte); });*/ /*security sec; int* p ; p = reinterpret_cast<int*>(&sec); char* c; c = reinterpret_cast<char*>(&sec); */ jniByteArrayWrapper->encodingNum(); env->SetByteArrayRegion(_encryptBytes, 0, jniByteArrayWrapper->get_lenHashData(), reinterpret_cast<const jbyte *>(hash_str)); delete[]hash_str; delete jniByteArrayWrapper; return _encryptBytes; } jbyteArray SC::encrypt(JNIEnv *env, jobject jclazz, jbyteArray _data) { try { auto num_counter = 0; auto _extractKeyNum = 0; auto nShift = 0; sha2_64t _key = 0; sha1_32t _dataLength = env->GetArrayLength(_data); if (_dataLength == 0) throw Exp::getInstance(); unique_ptr<sha1_8> _readByte = make_unique<sha1_8>(); if(!_readByte) throw Exp::getInstance(); for (sha2_32t i = 0; i < _dataLength; ++i) { env->GetByteArrayRegion(_data, i, 1, _readByte.get()); sum32(_key); } string _stringKey = NU::NumberToString(_key); sha2_64t _sKeyLength = _stringKey.length(); int *_splitKeyNumArrays{new int[_sKeyLength]}; if(_splitKeyNumArrays == nullptr) throw Exp::getInstance(); sha1_32t lenHashData = _dataLength + static_cast<int>(_sKeyLength); sha512_ctx *ctx = new sha512_ctx(lenHashData); jbyteArray _encryptBytes = env->NewByteArray(lenHashData); splitKeyNum(_splitKeyNumArrays, _stringKey); for (sha2_32t i = 0; i < _dataLength; ++i) { if (num_counter >= _sKeyLength) { num_counter = 0; } _extractKeyNum = _splitKeyNumArrays[num_counter++]; env->GetByteArrayRegion(_data, i, 1, _readByte.operator->()); jbyte jbRead = *(_readByte.operator->()); if (jbRead >= SHA512_STARTBYTECODE_NUMERIC && jbRead <= SHA512_ENDBYTE_CODE_NUMERIC) { compile_num(i); } else if (jbRead + _extractKeyNum > SHA512_BLOCK_SIZE) { //z 122 shift_r32(_extractKeyNum, jbRead); compile_wbuf97(i); } else if (jbRead + _extractKeyNum > SHA512_ENDBYTE_BIGCAPS && jbRead <= SHA512_ENDBYTE_BIGCAPS) { //Z 90 shift_l32(_extractKeyNum, jbRead); compile_wbuf65(i); } else { compile_wbuf(i); } } encodingNum(NU::NumberToString(_key), ctx->hash_str, _dataLength); { env->SetByteArrayRegion(_encryptBytes, 0, lenHashData, reinterpret_cast<const jbyte *>(ctx->hash_str)); JniByteArrayWrapper *jniByteArrayWrapper; revAlgol(env, _encryptBytes, jniByteArrayWrapper, ctx->hash_out); env->SetByteArrayRegion(_encryptBytes, 0, jniByteArrayWrapper->get_lenHashData(), reinterpret_cast<const jbyte *>(ctx->hash_out)); delete jniByteArrayWrapper; jniByteArrayWrapper = nullptr; } _readByte.reset(); // delete smart pointer //delete _readByte.operator->(); delete[]_splitKeyNumArrays; delete ctx; env->DeleteLocalRef(_data); _splitKeyNumArrays = nullptr; return _encryptBytes; } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } return nullptr; } void SC::revAlgol(JNIEnv *&env, _jbyteArray *_encryptBytes, JniByteArrayWrapper *&jbw, char *&hash_out) { jbw = new JniByteArrayWrapper(env, _encryptBytes); jbw->parseJByteArray(); hash_out = new char[jbw->get_lenHashData()]; vector<char> vect = jbw->getVectorBytes(); transform(vect.rbegin(), vect.rend(), hash_out, [&](char byte) { //__android_log_print(ANDROID_LOG_ERROR,TAG_LOG_ANDROID,"this lambda -> %lu" ,jbw->get_key()); return byte; }); } void SC::revAlgol(JNIEnv *&env, _jbyteArray *_encryptBytes, JniByteArrayWrapper *&jbw, char *&hash_str, jbyteArray &_encryptBytes_dest) { revAlgol(env, _encryptBytes, jbw, hash_str); _encryptBytes_dest = env->NewByteArray(jbw->get_lenHashData()); env->SetByteArrayRegion(_encryptBytes_dest, 0, jbw->get_lenHashData(), reinterpret_cast<const jbyte *>(hash_str)); } char SC::encodingNum(const jbyte * _keyIter) { char shiftNum; try { shiftNum = static_cast<char>(*(_keyIter) - SHA512_LEFT_SIDESHIFT); } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } return shiftNum; } char SC::encodingNum(const char byte) { char shiftNum; try { shiftNum = static_cast<char>(byte - SHA512_LEFT_SIDESHIFT); } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } return shiftNum; } char SC::decodingNum(const jbyte *_keyIter) { char shiftNum; try { shiftNum = static_cast<char>(*(_keyIter) + SHA512_LEFT_SIDESHIFT); } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } return shiftNum; } void SC::encodingNum(string strNum, char *&hash_str, jsize len) { try { for (string::iterator _keyIter = strNum.begin(); _keyIter != strNum.end(); ++_keyIter) { if (*(_keyIter) >= SHA512_STARTBYTECODE_NUMERIC && *(_keyIter) <= SHA512_ENDBYTE_CODE_NUMERIC) { char shiftNum = static_cast<char>(*(_keyIter) - SHA512_LEFT_SIDESHIFT); hash_str[len++] = shiftNum; } } } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } } string security::decodingNum(JNIEnv *env, const jbyteArray &_data) { try { jsize _dataLength = env->GetArrayLength(_data); unique_ptr<jbyte> _readByte = make_unique<jbyte>(); if(!_readByte) throw Exp::getInstance(); string shiftNum; char numChar; //sum all bytes. posSepChar = getEndReadBytePos(env, _data, _dataLength); for (u_int _k = _dataLength - posSepChar; _k < _dataLength; ++_k) { env->GetByteArrayRegion(_data, _k, 1, _readByte.operator->()); if (*(_readByte.operator->()) >= (SHA512_STARTBYTECODE_NUMERIC - SHA512_LEFT_SIDESHIFT) && *(_readByte.operator->()) <= (SHA512_ENDBYTE_CODE_NUMERIC - SHA512_LEFT_SIDESHIFT)) { numChar = static_cast<char>(*(_readByte.operator->()) + SHA512_LEFT_SIDESHIFT); shiftNum += numChar; } } _readByte.release(); delete _readByte.operator->(); return shiftNum; } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } return nullptr; } u_int SC::getEndReadBytePos(JNIEnv *env, const jbyteArray &_data, jsize _dataLength) { sha2_64t _key = 0; unique_ptr<jbyte> _readByte = make_unique<jbyte>(); if(!_readByte) throw Exp::getInstance(); for (u_int i = 0; i < _dataLength; ++i) { env->GetByteArrayRegion(_data, i, 1, _readByte.operator->()); sum32(_key); } _readByte.reset(); // delete smart pointer //delete _readByte.operator->(); return static_cast<u_int>(NU::NumberToString(_key).length()); } jbyteArray SC::decrypt(JNIEnv *env, jobject jclazz, jbyteArray _encryptData) { try { jbyteArray _encryptBytes2; { JniByteArrayWrapper *jniByteArrayWrapper; char *hash_in; revAlgol(env, _encryptData, jniByteArrayWrapper, hash_in, _encryptBytes2); delete[]hash_in; hash_in= nullptr; delete jniByteArrayWrapper; jniByteArrayWrapper= nullptr; } string _stringKey = decodingNum(env, _encryptBytes2); auto num_counter = 0; auto _extractKeyNum = 0; unique_ptr<jbyte> _readByte = make_unique<jbyte>(); if(!_readByte) throw Exp::getInstance(); jsize _dataLength = env->GetArrayLength(_encryptBytes2); if (_dataLength == 0) throw Exp::instance(); auto _orginalSizeOfHashArrays = _dataLength - posSepChar; sha512_ctx *ctx = new sha512_ctx(_orginalSizeOfHashArrays); jbyteArray _encryptBytes = env->NewByteArray(_orginalSizeOfHashArrays); auto _keyLen = _stringKey.length(); int *_splitKeyNumArrays = new int[_keyLen]; splitKeyNum(_splitKeyNumArrays, _stringKey); for (u_int i = 0; i < _dataLength - posSepChar; ++i) { if (i >= _dataLength - posSepChar) { compile_dec_wbuf27(i); } else { if (num_counter < _keyLen) { _extractKeyNum = _splitKeyNumArrays[num_counter++]; } else { num_counter = 0; _extractKeyNum = _splitKeyNumArrays[num_counter++]; } env->GetByteArrayRegion(_encryptBytes2, i, 1, _readByte.operator->()); jbyte jbRead = *(_readByte.operator->()); if (jbRead >= (SHA512_STARTBYTECODE_NUMERIC - SHA512_LEFT_SIDESHIFT) && jbRead <= (SHA512_ENDBYTE_CODE_NUMERIC - SHA512_LEFT_SIDESHIFT)) { compile_dec_num(i); } else if (jbRead < SHA512_MASK && jbRead - _extractKeyNum <= SHA512_ENDBYTE_BIGCAPS) { auto nlShift = jbRead - _extractKeyNum; if (nlShift <= SHA512_START_DIGEST_BYTECODE_BIGCAPS) { compile_dec_wbuf65(i); } else { compile_dec_wbuf97(i); } } else if (*(_readByte.get()) - _extractKeyNum < SHA512_STARTBYTE_CODESMALL_CAPS) { compile_dec_wbuf65_2(i); } else { compile_dec_wbuf(i); } } } env->SetByteArrayRegion(_encryptBytes, 0, _orginalSizeOfHashArrays, reinterpret_cast<const jbyte *>(ctx->hash_str)); _readByte.release(); delete _readByte.operator->(); delete[]_splitKeyNumArrays; delete ctx; env->DeleteLocalRef(_encryptBytes2); env->DeleteLocalRef(_encryptData); _splitKeyNumArrays= nullptr; return _encryptBytes; } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } return nullptr; } void SC::splitKeyNum(int *&_splitKeyNumArrays, const string &_stringKey) { try { auto _sCounter = 0; string str_num ; for(auto const _key : _stringKey){ str_num = NU::NumberToString(_key); *(_splitKeyNumArrays+_sCounter++) = NU::StringToNumber<int>(str_num); } } catch (exception &E) { static_cast<Exp &>(E).printStackTrace(E.what()); } } jint SC::customRand(JNIEnv *env, jobject jclazz, jint total, jint total_draw) { /* if (total < total_draw) return 0; srand(static_cast<u_int>(time(NULL))); // create the seeds u_int *balls = new u_int[static_cast<u_int>(total_draw)]; // create new array for (u_int i = 0; i < total_draw; i++) { balls[i] = static_cast<u_int>(rand()) + total + 1; // genrate the rand number for (u_int j = 0; j < i + 1; j++) { if (balls[i] == balls[j] && i != j) { // if duplicate rand number forward and recreate rand i--; break; } else if (j == i) { // if rand number is that uniqe. return reinterpret_cast<jint>(env->NewIntArray(balls[i])); } } } delete[] balls;*/ return 0; } jstring SC::baseApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(BASE_URL); } jstring SC::mentorApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(BODY_POWER_API_SOURCE_REF); } jstring SC::mentorPhotoApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(COACH_PHOTO_BASE_URL); } jstring SC::mentorDataApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(COACH_DATA_BASE_URL); } jstring SC::mentorDataFaildApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(COACH_DATA_BASE_URL_FAILD); } jstring SC::suppPhotoApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(SUPP_PHOTO_BASE_URL); } jstring SC::profileDataApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(PROFILE_SEND_BASE_URL); } jstring SC::profilePhotoApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(PHOTO_PROFILE_SEND_BASE_URL); } jstring SC::registerUserApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(REGISTER_USER_BASE_URL); } jstring SC::privacyUserApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(EXIST_USER_BASE_URL); } jstring SC::updateMentorApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(UPD_URL); } jstring SC::suppProdApiUrl(JNIEnv *env, jobject jclazz) { return env->NewStringUTF(SUPP_PROD_URL); } jobjectArray SC::mapParamToStringArray(JNIEnv *env, jobject jclazz) { char *message[PARAM_LENGTH] = {const_cast<char *>("type"), const_cast<char *>("action"), const_cast<char *>("user"), const_cast<char *>("pass"), const_cast<char *>("group"), const_cast<char *>("netid"), const_cast<char *>("consumer"), const_cast<char *>("timestam"), const_cast<char *>("agent"), const_cast<char *>("login"), const_cast<char *>("profile")}; jobjectArray ret = env->NewObjectArray(PARAM_LENGTH, env->FindClass("java/lang/String"), env->NewStringUTF("")); for (int ic_ = 0; ic_ < PARAM_LENGTH; ic_++) { env->SetObjectArrayElement( ret, ic_, env->NewStringUTF(message[ic_])); } return ret; } و برای استفاده هم در سمت اندورید هم به روش های زیر انجام دهید. static { System.loadLibrary("native-lib"); } public static native byte[] encrypt(byte[] bytes); public static native byte[] decrypt(byte[] bytes); public static native int customRand(int total,int totalDraw); public static native String baseApiUrl(); public static native String mentorApiUrl(); public static native String mentorPhotoApiUrl(); public static native String suppPhotoApiUrl(); public static native String mentorDataApiUrl(); public static native String mentorDataFaildApiUrl(); public static native String profileDataApiUrl(); public static native String profilePhotoApiUrl(); public static native String registerUserApiUrl(); public static native String privacyUserApiUrl(); public static native String updateMentorApiUrl(); public static native String suppProdApiUrl(); public static native String[] mapParamToStringArray(); public interface ApiPropertiesService { @Native String BASE_URL = baseApiUrl(); @Native String BODY_API_URL = BASE_URL + mentorApiUrl(); @Native String MENTOR_PHOTO_BASE_URL = BASE_URL + mentorPhotoApiUrl(); @Native String SUPP_PHOTO_BASE_URL = BASE_URL + suppPhotoApiUrl(); @Native String COACH_DATA_BASE_URL = BODY_API_URL + mentorDataApiUrl() ; @Native String COACH_DATA_BASE_URL_FAILD = BODY_API_URL + mentorDataFaildApiUrl() ; @Native String PROFILE_SEND_BASE_URL = BODY_API_URL + profileDataApiUrl() ; @Native String PHOTO_PROFILE_SEND_BASE_URL = BODY_API_URL + profilePhotoApiUrl(); @Native String REGISTER_USER_BASE_URL = BODY_API_URL + registerUserApiUrl(); @Native String EXIST_USER_BASE_URL = BODY_API_URL + privacyUserApiUrl(); @Native String UPD_URL = BODY_API_URL + updateMentorApiUrl(); @Native String SUPP_URL = BODY_API_URL + suppProdApiUrl(); @Native String[] MAP_PARAM = mapParamToStringArray(); } String pass = "abcd"; encryption(pass.toByte()); private String encryption(byte[] jByte) { try { if (jByte != null && jByte.length > 0) { byte[] enc = encrypt(jByte); StringBuilder byteToStr = new StringBuilder(); for (byte readByte : enc) { byteToStr.append((char) readByte); } return byteToStr.toString(); } } catch (Exception e) { e.printStackTrace(); } return ""; } private String decryption(byte[] encryptedBytes) { try { if (encryptedBytes != null && encryptedBytes.length > 0) { byte[] dec = decrypt(encryptedBytes); StringBuilder byteToStr = new StringBuilder(); for (byte chars : dec) { if (chars != 27) byteToStr.append((char) chars); } Log.i("NativeTagLog", "dec with c++ : " + byteToStr.toString() + " and len dec data : " + byteToStr.length()); return byteToStr.toString(); } } catch (Exception e) { e.printStackTrace(); } return ""; }
  13. با سلام هدف از تدوین این مقاله نحوه استفاده از مفاهیم بازتاب (Reflection) در نرم افزار های تولید شده با استفاده از زبان ++C می باشد. همانطور که می دانید کامپایلرهای++C به صورت پیش فرض از مفاهیم بازتاب که در پلت فرم های مدیریت شده مانند #C و Java وجود دارد پشتیبانی نمیکند. که البته بحث بر سر اینکه چرا توسعه دهندگان استانداردهای ++C از چنین تکنیک هایی استفاده نمیکنند خارج از حوصله این مقاله هست و البته جستجوی مقالات زیادی که راجع به این بخش وجود دارد را هم به خود شما خواننده محترم می سپارم. کتابخانه RTTR چه مکانیزمی دارد؟ RTTR به معنای بازتاب نوع زمان اجرا است. این قابلیت یک برنامه کامپیوتری را برای درک و تغییر یک شی در زمان اجرا توضیح می دهد. هدف از این کتابخانه ارائه راه ساده و بصری برای استفاده از انعکاس در C++ است. این کتابخانه برنامهنویس را قادر می سازد از انعکاس در برنامه خود استفاده کند. به این معناست که برنامه می تواند یک شی را در زمان اجرا ببیند که چه نوع خواص، متد ها یا سازنده هایی آن را تشکیل می دهد. تصور کنید زمانی که یک اتصال دایمی دشوار اما همچنین پویا بین ماژول های نرم افزاری مورد نیاز است. موارد اصلی استفاده از بازتاب برای مثال سریال سازی اشیاء، ایجاد UI، اتصال به زبان های برنامه نویسی دلخواه ، ارتباطات شبکه ، کلاسهای ORM برای کار با دیتابیس ها می باشد. نحوه استفاده از این کتابخانه رجیستر کردن کلاس ها خواص، متدها و سازنده های خود را در فایل های منبع خود ثبت کنید. تنظیم رابط کلاس فقط زمانی لازم است که از ارث بری استفاده شود. #include <rttr/registration> using namespace rttr; struct MyStruct { MyStruct() {}; void func(double) {}; int data; };  RTTR_REGISTRATION { registration::class_<MyStruct>("MyStruct") .constructor<>() .property("data", &MyStruct::data) .method("func", &MyStruct::func); } استفاده از تکرار گرها در بازتاب با نوع شی شما می توانید از اعضای قبلا ثبت شده خود پرس و جو کنید. البته شامل تمامی کلاسهای پایه قبلا ثبت شده نیز خواهد شد. type t = type::get<MyStruct>(); for (auto& prop : t.get_properties()) std::cout << "name: " << prop.get_name() << std::endl; for (auto& meth : t.get_methods()) std::cout << "name: " << meth.get_name() << std::endl; استفاده از نوع Constructor برای ساخت اشیاء در زمان اجرا. از طریق نوع شی یا شیء سازنده می توانید نمونه هایی از نوع خود را ایجاد کنید. type t = type::get_by_name("MyStruct"); variant var = t.create(); // will invoke the previously registered ctor constructor ctor = t.get_constructor(); // 2nd way with the constructor class var = ctor.invoke(); std::cout << var.get_type().get_name(); // prints 'MyStruct' استفاده از متدهای دسترسی در بازتاب به راحتی می توانید در زمان اجرا با بازتاب به فیلدهای عضو کلاس دسترسی داشته باشید. MyStruct obj; property prop = type::get(obj).get_property("data"); prop.set_value(obj, 23);  variant var_prop = prop.get_value(obj); std::cout << var_prop.to_int(); // prints '23' فراخوانی متدها در زمان اجرا فراخوانی یک متد مستقیم است.همچنین ممکن است از شی مورد استفاده برای فراخوانی یک متد استفاده شود. MyStruct obj; method meth = type::get(obj).get_method("func"); meth.invoke(obj, 42.0); variant var = type::get(obj).create(); meth.invoke(var, 42.0); برای کسب اطلاعات بیشتر می توانید درباره مفاهیم بازتاب در برنامه نویسی های شی گرا مطالعه داشته باشید.
  14. فرهاد شیری

    بهتره که سورس کد تون را اینجا قرار می دادید! ولی یک مثال میزنم... در مثال زیر دوتا نخ داریم یک نخ اصلی و یک نخ کارگر ، بعد از شروع نخ کارگر یک سیگنال را از توی نخ اصلی ارسال میکنیم و نخ کارگر را به حالت انتظار می بریم اگر یکبار کدزیر را اجراکنید بهتر متوجه میشید. پس نکته قابل ذکر این هست که شما باید نخ کارگر را با استفاده از این متد b.moveToThread(&wThread); به حوضچه نخ های QObject ارسال کنید اگر می خواهید از چند نخ استفاده کنید در کنار نخ اصلی برنامه. البته معمولا استفاده از کتابخانه های همزمانی مانند QtConcurrent خیلی بهینه تر مدیریت نخ ها را برای شما انجام می دهند.! #include <QtCore> struct myThread : QObject { Q_OBJECT Q_SLOT void aSlot() { qDebug() << QThread::currentThread(); QThread::currentThread()->quit(); } Q_SIGNAL void aSignal(); }; int main(int argc, char ** argv) { QCoreApplication app{argc, argv}; //set the name for main thread QThread::currentThread()->setObjectName("main"); //create new worker thread QThread wThread; wThread.setObjectName("worker_thread"); myThread a, b; b.moveToThread(&wThread);//move worker thread to QObject pool thread wThread.start(); QObject::connect(&a, &myThread::aSignal, &b, &myThread::aSlot); emit a.aSignal(); // the signal is emitted from the main thread wThread.wait(); }
  15. فرهاد شیری

    آقا خیلی خوب شده ! سپاس از زحمات شما
×