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

قاسم رمضانی منش

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

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

  • روز های برد

    20

تمامی مطالب نوشته شده توسط قاسم رمضانی منش

  1. قاسم رمضانی منش

    علیکم‌السلام و درود بر شما؛ راستش با توضیحاتی که دادید خیلی گیج شدم و منتظرم که وقتی باشد تا کتابی که پیشنهاد دادید را بخوانم، چون کدهایی که دوستمان ارسال کرده‌اند درواقع برای من اصلاً جواب نداد و Segmentation Fault داده. و تا به چیزی که امروز من یادگرفته‌ام می‌دانم که آدرس یک متغیر local را نباید از تابع برگرداند و این دقیقاً کاری هست که در کد انجام شده و کاری که من کرده‌ام و دلیلی که بهتر دیده‌ام این بوده که حافظه‌ای در Heap گرفته‌ام و آدرس آن را برگرداندم و این عمل بدون Segmentation Fault کار خود را انجام میدهد. امّا همینطوری که گفتم : اصلاً رفتار کد به درستی مشخص نبود و با توضیحات شما هم چیزی متوجه نشدم.
  2. قاسم رمضانی منش

    پس برای چه در خروجی اسمبلی تولید شده وجود ندارند ؟ در فیلمی که پیوند آن را ارسال کرده‌ام توضیحاتی که داده است : «توابع inline درواقع دستوراتشان در همان قسمت فراخوانی قرار گرفته و کامپایل می‌شد.» در خروجی اسمبلی دوّم درست است ما تابعی با برچسب max_int (اسم تابع ما در مثال) نداریم امّا فراخوانی آن صورت گرفته است : call max_int@PLT و این قسمتی هست که متوجه نمی‌شم که دقیقاً چی را فراخوانی کرده ؟
  3. قاسم رمضانی منش

    درود و خسته نباشید بر دوستان عزیز؛ در New Features In C درحال بررسی قابلیّت‌های اضافه شده به استانداردهای سی بوده‌اند، درمورد توابع inline به چه صورت کامپایل می‌شود ؟ یک نمونه به این‌صورت نوشته‌ام : int max_int(const int i, const int j) { return (i > j) ? i : j; } int main (void) { return max_int(10, 15); } و خروجی اسمبلی به این‌صورت می‌باشد : .file "main.c" .text .globl max_int .type max_int, @function max_int: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl %edi, -4(%rbp) movl %esi, -8(%rbp) movl -4(%rbp), %eax cmpl %eax, -8(%rbp) cmovge -8(%rbp), %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size max_int, .-max_int .globl main .type main, @function main: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $15, %esi movl $10, %edi call max_int popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size main, .-main .ident "GCC: (GNU) 9.1.0" .section .note.GNU-stack,"",@progbits و هنگامی که تابع را به صورت inline‌ تعریف می‌کنم: .file "main.c" .text .globl main .type main, @function main: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $15, %esi movl $10, %edi call max_int@PLT popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size main, .-main .ident "GCC: (GNU) 9.1.0" .section .note.GNU-stack,"",@progbits هر دو در اینجا max_int را فراخوانی کرده‌اند امّا در خروجی دوّم هیچ label برای max_int تعریف نشده است ! به چه صورت عمل می‌کند ؟
  4. قاسم رمضانی منش

    درود بر شما؛ بله مشکل دارد، همانطوری که خودتان هم گفتید دارید آدرس یک متغیر محلی را از تابع بر می‌گردانید که این اخطار را هم از سمت کامپایلر هنگام کامپایل آن تابع دریافت می‌کنید ‌: $ warning: function returns address of local variable و برنامهٔ شما هم به احتمال زیاد Segmentation Falut داده و از بین می‌رود. برنامهٔ شما ممکن است که خروجی درستی نداشته باشد، چراکه دارید از یک حافظه‌ای داده را می‌خوانید که اصلاً وجود ندارد (حافظه آزاد شده است). در کامپایلر MSVC2017 و سیستم‌عامل Windows 7 64bit کد را برای شما کامپایل و بدون مشکل اجرا می‌کند امّا خروجی درستی ندارید. در کامپایلر MinGW و سیستم‌عامل Windows 7 64bit کد را کامپایل و اخطاری که در بالا اشاره کرده‌ام را داده و در هنگام اجرا برنامه با Segmentation Fault رو به رو می‌شود. کامپایلرهای GCC و‌ Clang در سیستم‌عامل ArchLinux اخطار بالا را داده و همانند MinGW عمل می‌کند. کامپایلر TCC در سیستم‌عامل ArchLinux نیز همانند MSVC2017 عمل می‌کند. بهتر است که تابع را به این شکل بازنویسی کنید : char* doXOR(char* cData1, char* cData2) { char* cData = malloc(256); assert(cData); for (int i = 0; i < 255; ++i) { cData[i] =cData1[i] ^ cData2[i]; } cData[255] = '\0'; return cData; } و همچنین موقع استفاده : int main (void) { /* ... */ char* tmp = doXOR(cData1, cData2); strcpy(cData3, tmp); printf("%s\n", cData3); free(tmp); tmp = NULL; return EXIT_SUCCESS; }
  5. قاسم رمضانی منش

    درود بر شما، سلامت باشید؛ برای اینکار بهتر هست که یک کلاس به عنوان Adapter درست کنید که درواقع ارتباطات شما را با این کلاس پوشش بدهد و آن کلاس را در سمت QML استفاده کنید. برای استفاده از داده‌های خودمان در سمت QML راه‌های مختلفی هست که باید مطالعه کنید و بسته به نیازتون انتخاب کنید؛ سند روش‌های برقراری ارتباط بین ++C و QML. یک مثال در این قسمت آقای اسدزاده زده‌اند و برای نمونهٔ اضافه بنده هم یک مثال از این روش، به‌ اینصورت‌که یک کلاس برای ارتباط برقرار کردن با کلاس QVector درست کرده‌ام : [پیوند فایل somewrapper.h] class SomeWrapper : public QObject { Q_OBJECT Q_PROPERTY(QString StringWrap READ readCurrentString WRITE addAnotherString) public: void addAnotherString(const QString& string) { REPORT(string, "ourStringList"); REPORT(string, "currentString"); this->currentString = string; this->ourStringList.push_back(string); } QString readCurrentString(void) const { return this->currentString; } Q_INVOKABLE QString getSomeString(const int& index) const { return this->ourStringList.at(index); } private: QVector<QString> ourStringList; QString currentString; }; و به این‌صورت آن را برای موتور QML معرفی کرده‌ام : [پیوند فایل main.cpp] int main (int argc, char** argv) { QGuiApplication application(argc, argv); QQmlApplicationEngine qmlApplication; SomeWrapper stringBook; qmlApplication.rootContext()->setContextProperty ("StringBook", &stringBook); qmlApplication.load(QUrl::fromLocalFile("../../main.qml")); return application.exec(); } و حال به راحتی می‌توانم داده‌های مورد نیاز را به سادگی از سمت QML دریافت کرده و با پردازش آن در کلاس SomeWrapper به کلاس QVector ارسال کنم : [پیوند فایل main.qml] TextField{ id: user_search_input placeholderText: "خانهٔ مورد نظر را وارد کنید" horizontalAlignment: TextInput.Center } Button{ text: "گَشتن" onClicked: { user_search_input.text = StringBook.getSomeString(user_search_input.text) } }
  6. قاسم رمضانی منش

    درود؛ تشکر و خدا قوّت. درمورد «توابع بدون آرگمان» که گفته‌اید برای جلوگیری از تزریق کد باید void را قرار بدهیم، لطفاً درصورت امکان این مورد را با یک مثال توضیح بیشتر بدهید و یا اینکه پیوند مقاله/سندی که توضیح داده است را معرفی کنید چرا که به درستی علّت را متوجه نشدم.
  7. درود؛ درمورد نحوهٔ کار استاندارد‌ها نمی‌دانم ولی توی استاندارد توضیحی درمورد اینکه چطوری پیاده‌سازی بشه نداده، این مورد ظاهراً به‌عهدهٔ کامپایلره. مثلاً در پیاده‌سازی‌ای که GCC از N4806 کرده (فعلاً Clang هیچ پیاده‌سازی‌ای نداره) از توابع داخلی خود کامپایلر استفاده کرده : [آدرس فایل در مخزن گیت] // 14.1.2, source_location creation static constexpr source_location current(const char* __file = __builtin_FILE(), const char* __func = __builtin_FUNCTION(), int __line = __builtin_LINE(), int __col = 0) noexcept { source_location __loc; __loc._M_file = __file; __loc._M_func = __func; __loc._M_line = __line; __loc._M_col = __col; return __loc; } پیاده‌سازیه توابع داخلی (پیوند).
  8. قاسم رمضانی منش

    درود بر دوستان عزیز؛ وقتی در دایرکتوری‌ای که کامپوننت‌های خودمان را قرار داده‌ایم و با استفاده از فایل qmldir آن‌ها را معرفی کردیم محیط QtCreator شروع به گیج زدن می‌کند و باید حتماً کل برنامه را یک‌بار Restart کرد. آیا راهی برای حل این مشکل وجود دارد ؟
  9. قاسم رمضانی منش

    تشکر بابت توضیحاتتون ممنون؛ اصرارم این بود که فکر می‌کردم اینکار ساده‌ای هست و نیازی نیست که بی‌مورد توابع libc را فراخوانی کنیم. البته به گمانم بشه کارهایی کرد ولی بهتر است که کمی اسمبلی را مطالعه کنم.
  10. قاسم رمضانی منش

    با تشکر از شما، متوجه شدم که چگونه باید اشیاء را در ScrollView قرار بدم : ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") color: "gray" Rectangle{ anchors.centerIn: parent width: parent.width / 2; height: parent.height / 2 border.color: "black" ScrollView{ anchors.fill: parent clip: true anchors.centerIn: parent Column{ x: 110 Repeater{ model: 40 Rectangle{color: "red"; border.color: "yellow"; width: 80; height: 80} } } } } } خروجی نمونهٔ بالا :
  11. قاسم رمضانی منش

    درود بر دوستان عزیز؛ چگونه می‌توان Itemهایی که در ScrollView قرار دارند را وسط‌چین کرد ؟: ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") color: "gray" ScrollView{ width: parent.width / 2; height: parent.height / 2 clip: true anchors.centerIn: parent Column{ Repeater{ model: 40 Rectangle{color: "red"; border.color: "yellow"; width: 80; height: 80} } } } } در نمونهٔ بالا مثلاً می‌خواهم که تمامی Rectangleها در وسط ScrollView رندر بشوند.
  12. قاسم رمضانی منش

    درود بر دوستان عزیز؛ کامپوننت TextInput به‌صورت پیش‌فرض وقتی اشاره‌گر ماوس را روی آن می‌بریم هیچ تغییر شکلی بر روی اشاره‌گر ماوس اعمال نمی‌شود، برای حل این مشکل بنده به این‌صورت عمل کرده‌ام : TextInput{ . . MouseArea{ anchors.fill: parent cursorShape: Qt.IBeamCursor } . } امّا مشکلی که وجود دارد این MouseArea یک لایه بر روی TextInput‌ ایجاد می‌کند که مثلاً اگر قابلیّت selectByMouse را در TextInput فعال کرده‌باشیم دیگر کارنخواهد کرد. چه راه‌حلی برای این مشکل وجود دارد ؟
  13. قاسم رمضانی منش

    میشه کاری کرد که اصلاً دست به اشاره‌گر string نزنه ؟ یعنی همان کد بالا ولی هیچ تغییری در محتوای اشاره‌گر string ایجاد نکنه که باعث بشه به ناکجاآباد اشاره‌کنه ؟ بله درست متوجه شدید، و بعد چون اون اشاره‌گر از نوع کل‌آرایه هست من تبدیلش کردم به نوع *char که بتونم خونه‌های ۱ بایتی را ازش کم کنم؛ که میشه خونهٔ آخر آرایه. یه کم کامل‌تر بگم : وقتی ما می‌نویسیم arr* یعنی مقدار خانه‌ای که arr به آن اشاره می‌کند را درخواست می‌کنیم (فرض می‌گیریم arr یک []char است). حالا وقتی می‌گوییم arr& یعنی آدرس خانه‌ای که arr به آن اشاره می‌کند را می‌گیریم، با تفاوتش با arr + 2& این است که arr& آدرس کل خانه‌های arr را به ما می‌دهد به جای آدرس یک خانه. پس وقتی که arr + 1& می‌گوییم درواقع یک همچین چیزی است : /* ================= | x | x | x | x | ================= \---+---/ | char arr[]: -+ ================= | x | x | x | x | ======|========== | | arr + 1 : -+ ================= | x | x | x | x | ================= ^ | &arr + 1 : -+ / ================= +> | x | x | x | x | \ ================= +--------+ | &arr : ----+ ================= -------------... | x | x | x | x | | | | | |... ================= -------------... ^ +----------+ | &arr + 1: ----+ */ و در انتها وقتی که ما نوع اشاره‌گر را به *char تغییر می‌دهیم و یک واحد کم می‌کنیم، درواقع یک واحد از نوع *char کم‌ می‌شود به جای یک واحد از نوع arr&. و اینطوری می‌توانیم به خانهٔ آخر آرایه به راحتی دسترسی داشته باشیم چرا که آن خانه در دسترس است. امّا اینکه چرا نمی‌توانم مقداری درآن خانه قرار بدم و آن رفتار کامپایلر اتفاق می‌اٌفتد عجیبه. من فقط آدرس را می‌گیرم، اصلاً هیچ دسترسی به آن خانه ندارم که بخواد مشکلی ایجاد کنه؛ فقط آدرس را می‌گیرم و واحدهایی (به اندازهٔ مقدارحافظه‌ای که char می‌گیرد) ازش کم‌ می‌کنم که بتونم به خانهٔ آخر آرایه دسترسی داشته‌باشم، نمونه : #define END_OF_ARRAY(type, arr, index) \ (*((type*) (&arr + 1) - index)) int main (void){ char string[] = "ghasem is here"; printf("%c\n", END_OF_ARRAY(char, string, 2)); printf("%s\n", string); return 0; }
  14. قاسم رمضانی منش

    متشکرم از توضیحتان رفتار کامپایلر را برای تولید آن کد اسمبلی را زیاد متوجه نشدم، کاری که کردم : اضافه کردن به آدرسی که به کل آرایه اشاره می‌کنه، که باعث میشه آدرس بعد از آرایه را به ما بده. سپس type اون آدرس را به تبدیل به نوع *char می‌کنم. و یک واحد (char) از آن آدرس کم می‌کنم که میشه خونهٔ آخر آرایه ما. امّا ظاهراً اون اتفاقی که می‌خواستم صورت نگرفته. درمورد روش‌هایی که پیشنهاد دادید : اینجا متوجه آن ۴ واحد اضافه کردن آخری نشدم، شما آدرس خانهٔ چهارم آرایه را تبدیل به *char کردید و سپس چهار واحد اضافه کردید (چرا ؟) و بعد به مقدارَش اشاره کردید.
  15. درود بر دوستان عزیز؛ برای اضافه کردن یک کاراکتر به انتهای رشته شاید افراد به این‌صورت عمل کنند : string[ strlen(string) ] = char; امّا من خواستم بدون وابسته بودن این قسمت به libc؛ این عمل انجام شود به این‌صورت عمل کردم : int main (void){ /* Define variable */ char c = 'm'; char* string = NULL; /* Allocating memory */ string = malloc(7); /* Copy char into `string` */ strcpy(string, (char*)"ghase"); /* Append `c` to end of `string` */ *((char*)(&string + 1) - 2) = c; *((char*)(&string + 1) - 1) = '\0'; /* Result */ printf("%s\n", string); return EXIT_SUCCESS; } امّا با سیگنال SIGSEGV در تابع __strlen_sse2() هنگام فراخوانی printf() مواجه می‌شوم، کلاً حافظهٔ دریافتی از طریق Derefrence کردن string مقادیرش قابل دسترسی نیست (پیغامی که GDB نشان می‌دهد). ولی همچنان می‌توانم به‌اینصورت به مقداردهی که کرده‌ام دسترسی داشته‌باشم : printf("%c\n", *((char*)(&string + 1) - 2)); الآن چه اتفاقی برای حافظهٔ متغیر string می‌افتد ؟
  16. درود و خسته‌نباشید به دوستان؛ می‌خواهم حالتی را مانند RadioButton که فقط می‌توان «یکی‌ از چندتا» را انتخاب کرد را در دکمه‌هایی که خودم نوشته‌ام پیاده کنم، در حالت عادی به این‌صورت عمل کرده‌ام و خب مشخصاً راه‌حل خوبی نیست استفاده از تابع ()fundOutAndTurnOnButtonLight؛ به چه روشی می‌توان بهتر عمل کرد ؟ main.qml ApplicationWindow { id: root; visible: true width: 640; height: 480 color: "gray" function findOutAndTurnOnButtonLight(id){ switch(id){ case pageOne: pageTwo.isSelected = false pageThree.isSelected = false break case pageTwo: pageOne.isSelected = false pageThree.isSelected = false break case pageThree: pageOne.isSelected = false pageTwo.isSelected = false break } id.isSelected = true } Row{ id: kepper anchors.centerIn: parent spacing: 20 MyRec{ id: pageOne onButtonClicked: findOutAndTurnOnButtonLight(pageOne) } MyRec{ id: pageTwo onButtonClicked: findOutAndTurnOnButtonLight(pageTwo) } MyRec{ id: pageThree onButtonClicked: findOutAndTurnOnButtonLight(pageThree) } } } و کامپوننت MyRec که در فایل MyRec.qml می‌باشد : Item { id: root width: 100; height: 100 property bool isSelected : false signal buttonClicked() Rectangle{ id: myButton anchors.fill: parent color: "red" width: parent.width / 4 height: parent.height / 4 } Rectangle{ id: bar anchors{ bottom: myButton.bottom horizontalCenter: myButton.horizontalCenter } color: "blue" width: myButton.width / 2 height: 5 visible: isSelected } MouseArea{ id: clickableArea anchors.fill: myButton onClicked: buttonClicked() } states:[ State{ name: "entered" when: clickableArea.pressed PropertyChanges{ target: myButton color: "yellow" } } ] }
  17. قاسم رمضانی منش

    درود و خسته‌نباشید به دوستان؛ در مستندات RadioButtonStyle مثالی به این‌صورت زده شده : RadioButton { text: "Radio Button" style: RadioButtonStyle { indicator: Rectangle { implicitWidth: 16 implicitHeight: 16 ... } ... } ... } امّا RadioButton خاصیّتی تحت عنوان style ندارد، آیا این مثال اشتباه است ؟ و چگونه می‌توان از RadioButtonStyle استفاده کرد ؟ این مورد دربارهٔ CheckBoxStyle نیز صدق می‌کند. ویرایش: باتوجه به مستندات : Import Statement: import QtQuick.Controls.Styles 1.4 Since: Qt 5.1 قابلیّت style در ویرایش 1.4 از ماژول QtQuick.Controls.Styles موجود می‌باشد، و پس از import کردن آن خطا رفع می‌شود. آیا اضافه کردن نسخهٔ 1.4 و 2.13 تداخلی به وجود می‌آورد ؟
  18. قاسم رمضانی منش

    درود و خسته‌نباشید به دوستان؛ درحال طراحی یک رابط‌کابری‌ساده بوده‌ام که خواستم قسمت رنگ‌آمیزی Itemها و Fontها و ... به راحتی قابل تغییر و برنامه‌ریزی باشد. اینکار را با استفاده از یک فایل QML جدا به اسم Style.qml به شکل زیر انجام دادم : pragma Singleton import QtQuick 2.13 Item { property int textinputTextSize : 22 property color transparent : "transparent" property color bluredColor : "#5AAFAAAA" property int tabBarWidth : 50 property int tabBarHeight : 75 property int tabBarIconSize : 44 property int tabBarTextSize : 20 property color tabBarIconColor: "#81D8DE" property color tabBarTextColor: "#059EAB" property color tabBarBackColor: "#0571AB" property alias sahelRegular : sahel_font.name property alias fontAwesome : font_awesome.name FontLoader{ id: sahel_font source: "qrc:/assets/fonts/sahel/Sahel-FD-WOL.ttf" } FontLoader{ id: font_awesome source: "qrc:/assets/fonts/awesome/fontawesome-regular.ttf" } property color mainpageColor : "#E3F2FD" property color mainpageToolbarColor : bluredColor } آیا این روش بهینه و درست است ؟ و یا راه بهتری هم وجود دارد ؟
  19. قاسم رمضانی منش

    درود بر شما؛ همچنین برای بهره‌وری بهتر درصورتی‌که کامپایلر GCC یا Clang را دارید، می‌توانید از قابلیّت «Braced-groups Within Expressions» استفاده و حالتی را شبیه به توابع Lambda را پیاده‌سازی کنید : #define lambda(x) ({x}) int main () { printf("%d\n", lambda( int i = 0; printf("%d\n", i); i = 10; )); return 0; }
  20. قاسم رمضانی منش

    @فرهاد شیری درود بر شما؛ بابت مبتدی بودن سوأل عذرخواهی می‌کنم؛ ابهام‌هایی در قسمت‌هایی از کد برایم وجود داشت که درست متوجه نشدم. در این قسمت : explicit CProperty(const property_type& rhs) : m_property(rhs) ,length(0) ,data(get()) { operator =(rhs); } هدف‌تان از ;operator =(rhs) چه بوده ؟ مگر عملگر = نیاز به دو عملوند ندارد ؟ چگونه به یک‌باره فراخوانی شده ؟ و چه نیازی بوده ؟ در قسمت دیگر: property_type& get(){ return *(reinterpret_cast<property_type*>(&const_cast<property_type&>(m_property))); } متوجه هدفتان از این تبدیل‌های پیاپی نشدم. با تشکر از شما.
  21. قاسم رمضانی منش

    کتابخانه‌های استاتیک و داینامیک (پویا)

    توضیحات موردنیاز، قبلاً در این‌پیوند داده شده. حال بیاید ببینیم در عمل چگونه‌است ؟ Static Library یا کتابخانه‌های استاتیک : معمولاً تحت عنوان Archives هم شناخته می‌شوند، یک Static Library شامل مجموعه‌ای از Object-Fileها هست. Object-Fileها سورس‌های کامپایل‌ شدهٔ ما به زبان‌ماشین هستند. این فایل‌ها قابل اجرا نیستند چراکه هنوز کتابخانه‌های موردنیازشان Link نشده. برای کامپایل به‌صورت Object-File از فلگ -c استفاده می‌کنیم : $> cc -c func.c $> cc -c main.c $> cc *.o -o output در اینجا ما سورس‌کدهای func.c و main.c را فقط کامپایل کردیم و بعد (در خط سوّم) Object-Fileها را به کامپایلرمان دادیم تا عمل لینک کردن کتابخانه‌ها و خروجی‌نهایی را تولید کند. برای ساخت Static Library ما از Object-File‌ها به همراه برنامهٔ ar استفاده می‌کنیم، به این‌صورت که اوّل Object-Fileها را تولید می‌کنیم : $> cc -c func1.c $> cc -c func2.c و حالا یک کتابخانه متشکل از Object-Fileها برای ساخت Static-Libraryمان خروجی می‌گیریم : $> ar rcs libfunc.a func1.o func1.o خب ! در این قسمت دو نکتهٔ کوچک و مهم وجود دارد : فایل‌هایی که با استفاده از فلگ -c کامپایل می‌کنید، خروجی‌حاصل فایلی با همان نام فایل ورودی به همراه پسوند .o می‌باشد. اسم کتابخانهٔ شما باید به‌صورت lib*.(a|os) باشد. و این‌چیزی هست که Linker به دنبال آن برای لینک‌کردن می‌گردد. برای کتابخانه‌های‌استاتیک ما از پسوند .a استفاده می‌کنیم و برای کتابخانه‌های‌داینامیک از .so . حال برای استفاده از این کتابخانه‌ما نیاز به دوکار کوچک داریم هنگام کامپایل نهایی داریم : $> cc main.c -L. -lfunc -o output فلگ -L برای مشخص کردن دایرکتوری‌ای که کتابخانهٔ ما در آن قرار دارد استفاده می‌شود. (میدانیم که در UNIX هر دایرکتوری دارای دو لینک می‌باشد؛ یک . (dot) که اشاره به دایرکتوری جاری دارد و.. (dot-dot) که اشاره به دایرکتوری-پدر (parent-directory یا دایرکتوری بالایی دارد). فلگ -l برای مشخص کردن اسم کتابخانهٔ ما استفاده می‌شود، دیدید که ما فقط اسم func را آوردیم، چرا که خود تصور می‌کند اوّل اسم فایل lib و پسوند آن .a یا .so می‌باشد. یک نمونهٔ عملی را می‌توانید از این‌قسمت امتحان کنید : در این مثال از GNU Make استفاده شده است، درصورتی‌که آشنایی ندارید می‌توانید از این‌قسمت با GNU Make آشنا بشوید. امّا نکته‌ای که قابل ذکر هست : در این‌جا شما فقط کتابخانه‌ای که خودتان نوشتید را به‌صورت Static لینک کردید، کتابخانه‌هایی مثل glibc به‌صورت خودکار درحالت Dynamic لینک می‌شوند. Shared Library یا کتابخانه‌ داینامیک : در این روش بازهم ما نیاز به Object-Fileهای سورس‌کد‌ها داریم، با تفاوت اینکه باید فلگ -fPIC یا -fpic را اضافه کنیم که به معنی Position-independent Code می‌باشد؛ می‌دانید که Shared Libraryها یک‌بار فقط در حافظه بارگذاری می‌شوند از این رو نیاز است که سورس‌کدماشینی که تولید می‌شوند وابسته به این نباشد که در جای به خصوصی از حافظه بارگذاری شود. خب Object-Fileها را به صورت PIC کامپایل می‌کنیم : $> cc -c -fPIC add.c $> cc -c -fPIC sub.c حال باید کتابخانهٔ‌اشتراکی خود را با استفاده از فلگ -shared ایجاد کنیم : $> cc -shared add.o sub.o -o libmat.so در اینجا ما از فلگ -shared استفاده کردیم و Object-Fileهای تولیدشده را به عنوان ورودی وارد کرده‌ایم. و حالا می‌توانیم از shared library خودمان استفاده کنیم : $> cc main.c -o output -L. -lmath حال بیاید برنامه را اجرا کنیم : $> ./output ./output: error while loading shared libraries: libmat.so: cannot open shared object file: No such file or directory چرا ؟ به خاطر اینکه linker در آدرس‌های تعریف شده به دنبال کتابخانهٔ‌اشتراکی libmat.so می‌گردد. راه‌های مختلفی برای مشخص کردن مسیر کتابخانهٔ خودمان وجود دارد. انتقال کتابخانهٔ خود به آدرس /usr/lib دستکاری LD_LIBRARY_PATH ... راه‌های مختلف را می‌توانید از لینک‌های زیر دنبال کنید : https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/GCC/create-libraries/index https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html موفق‌وپیروز باشید .
  22. قاسم رمضانی منش

    درود بر شما؛ برای اینکار می‌توانید شما از QScrollArea استفاده کنید. این کلاس یک منطقهٔ‌نمایش Widgetها و یک QScrollBar را به شما می‌دهد، و شئ را که می‌خواهید Scroll کنید را باید به عنوان Child Widget به آن معرفی کنید. برای مثال : #include <QApplication> #include <QDialog> #include <QGroupBox> #include <QList> #include <QScrollArea> #include <QTextEdit> #include <QVBoxLayout> int main(int argc, char** argv) { QApplication application(argc, argv); QDialog dialog; QVBoxLayout layout; QScrollArea scroll(&dialog); QGroupBox groupedArea; QList<QTextEdit*> widgets; for (int i {}; i < 20; ++i) { widgets.append(new QTextEdit); layout.addWidget(widgets.at(i)); } scroll.setWidget(&groupedArea); scroll.setWidgetResizable(true); groupedArea.setLayout(&layout); dialog.show(); return application.exec(); } دقّت کنید که باید حتماً تابع setWidgetResizable را با مقدار true برای تغییر اندازهٔ مناسب Widget فراخوانی کنید. خروجی حاصل از کد بالا : با تشکر از آقای‌رضوی.
  23. قاسم رمضانی منش

    @nabegheh95 درود بر شما؛ لازم به ذکر بود که، برنامهٔ Microsoft Visual Studio یک IDE توسعه داده شده توسط شرکت Microsoft می‌باشد. و برای توسعهٔ هرچه بهتر برنامه‌های سیستم‌عامل Windows تحت Microsoft .Net می‌باشد. درواقع شما با کامپایلر Microsoft Visual C++.Net کارکردید. برای فریمورک Qt هم یک IDE بسیارعالی وجود دارد که سرعت توسعهٔ نرم‌افزار با استفاده از این فریمورک را افزایش می‌دهد، پس پیشنهاد می‌کنم به جای استفاده از آن افزونه مستقیم از این IDE استفاده کنید چرا که یک IDE بسیار خوب نیز برای ++C\C می‌باشد. تنها پیشنهاد می‌شود که در سیستم‌عامل Microsoft Windows از کامپایلر Microsoft Visual C++.Net استفاده کنید، این کامپایلر برای سیستم‌عامل خود به خوبی عمل می‌کند. هرچند که باید حواستان به تنبلی‌های مایکروسافت باشد مواردی مثل مورد زیر اصلاً پیاده‌سازی نشده‌اند: void char_exception() throw(int){ throw 'x'; } int main(void){ try{ char_exception(); } catch (...){ std::cout << "Caught it." << std::endl; } return 0; } توضیح. فریمورک Qt یک مجموعهٔ عظیم از کتابخانه‌ها می‌باشد، که تماماً نیز در این‌سایت مستند شده‌اند. برای رفع ابهامات کافی است که مستندات را به دقّت مطالعه و نمونه‌های نوشته شده را بررسی و امتحان کنید. اجرا شدن یک فایل، بسته به کرنل یک سیستم‌عامل و نحوهٔ پیاده‌سازی آن می‌باشد. پس مسلماً ساختاری که در کرنل Windows NT به عنوان فایل اجرایی شناخته شده است، در کرنل Linux قابل قبول نیست. برای اطلاعات بیشتر درمورد این ساختارها می‌توانید ساختار PE و ELF را بررسی کنید. در حالت ایده‌آل، بلی باید تلاش داشته‌باشید که از APIهایی که Qt فراهم می‌کند استفاده کنید، امّا همیشه این کار شدنی نیست. شما همیشه نیازی به استفاده از Qt‌ ندارید و ممکن است قابلیّتی در یک سیستم‌عامل نیاز داشته‌باشید که مشابه آن در یک سیستم‌عامل دیگر متفاوت هست. برای مثال : این سورس Telegram/ThirdParty/minizip/ioapi.c هست، ببینید به چه صورت در خط‌های ۱۳ و ۱۷ و ۲۲ بسته به سیستم‌عامل مقصد مشخص کرده‌است که چه توابعی باید کامپایل شوند. با این روش شما درحالی که از قابلیّت خاص یک سیستم‌عامل استفاده کردید ولی برنامهٔ شما Cross-Platform می‌باشد. پیشنهاد می‌کنم کتاب «++API Design For C» نوشتهٔ آقای «Martin Reddy» را مطالعه کنید.
  24. قاسم رمضانی منش

    @Alireza4 درود؛ اینکه چه کاری انجام بدهید و به کدام راه برید، تماماً بستگی به خودتان دارد. پیشنهاد می‌کنم که قشنگ درمورد کاری که می‌خواهید انجام بدید تحقیق کنید : - هدفتان از برنامه‌نویسی چیست ؟ - چقدر حوصلهٔ یادگیری مطالب را دارید ؟ - چقد دید سیستمی به برنامه‌نویسی دارید ؟ و ..، این مطلب را حتماً مطالعه کنید : کدام زبان برنامه‌نویسی را انتخاب کنم ؟ ، در این مقاله توضیحات لازم داده شده که بتونید خودتان تصمیم بر انتخاب زبان بگیرید. چرا که باید بدونید «درسته‌که زبان سی‌پلاس‌پلاس قدرت زیادی داره» امّا باید بدونید که هرچیز خوبی بالاخره هزینه‌ای هم داره و یادیگری کار کردن با این زبان به شش‌ماه تموم نمیشه، برای اینکه دراین‌باره هم بیشتر اطلاعات کسب کنید مقالهٔ چرا و چگونه باید ++C را یادبگیریم ؟ ، شاید اصلاً چیزی نبود که شما فکر می‌کردید.
  25. قاسم رمضانی منش

    @MahdiGameMaker خطای «دوباره پاک کردم پکیج ها رو و بعد نصب کردن باز هم ارور میده»،‌ ارور خوبی نمی‌باشد که ما نیز راهنمایی‌ای برای آن بکنیم. لطفاً یک لاگ با اطلاعات کافی (از طریق یک سرویس paste) ارائه بدید.
×
×
  • جدید...