1660575900
Trước khi hiểu quá tải hàm tạo, trước tiên chúng ta cần hiểu hàm tạo là gì. Các hàm tạo là các phương thức duy nhất được gọi tự động khi chúng ta tạo một đối tượng lớp. Mục đích chính của các hàm tạo là khởi tạo các thành viên dữ liệu của đối tượng mới .
Trong nạp chồng phương thức khởi tạo C ++, chúng ta có thể có nhiều hơn một phương thức khởi tạo trong lớp có cùng tên, miễn là mỗi phương thức có một danh sách các đối số khác nhau. Nó khá giống với quá tải chức năng .
Có ba loại hàm tạo:
Bây giờ đến với nạp chồng hàm tạo , chúng ta có nhiều hơn một hàm tạo trong lớp, nhưng chúng khác nhau bởi số lượng đối số hiện diện.
Các thuộc tính của hàm tạo cần lưu ý khi nạp chồng một hàm tạo:
Khi chúng ta thêm nhiều hơn một hàm tạo vào một lớp, chúng ta gọi nó là nhiều hàm tạo.
Quá tải hàm tạo rất giống với quá tải hàm .
Hàm tạo nạp chồng thay đổi số lượng đối số trong danh sách tham số hiện tại của hàm tạo. Do đó, chúng ta có thể sử dụng các hàm tạo của cùng một lớp cho các mục đích khác nhau.
Giả sử chúng ta phải tạo một lô cho một nhóm sinh viên cụ thể, có thể là 500 sinh viên trong một lô duy nhất và biến class_no được đặt là 9 cho tất cả sinh viên vì tất cả họ đều ở trong lớp 9.
Sẽ rất tẻ nhạt khi cấp biến class_no 500 lần bằng 9 cho tất cả học sinh. Đó là lý do tại sao chúng tôi sử dụng các hàm tạo. Chúng ta tạo một đối tượng của lớp và chuyển biến class_no làm đối số của hàm tạo để đặt giá trị class_no = 9 cho tất cả 500 sinh viên.
Xem cú pháp mã sau đây.
class A
{
A()
{
body; //constructor with no parameter
}
A(int a, int b)
{
body; //constructor with 2 parameters
}
};
Ví dụ 1: Viết chương trình nạp chồng hai hàm tạo, một hàm chứa hai tham số để tìm diện tích hình chữ nhật và một hàm tạo một tham số để tìm diện tích hình vuông.
#include <iostream>
using namespace std;
class Area
{
public:
Area()
{
cout << "Class and object successfully created" << endl;
}
Area(int length, int breadth) /*Creating a constructor with 2 parameter*/
{
cout << "Area of the rectangle =" << length * breadth << endl;
}
Area(int side) /*Creating a constructor with 1 parameter*/
{
cout << "Area of the square = " << side * side << endl;
}
};
int main()
{
Area obj1;
Area obj2(5, 6); /*Initializing the value of length=5 and breadth=6*/
Area obj3(5); /*Initializing the value of side of square=5*/
return (0);
}
Xem kết quả sau.
Ví dụ 2:
Viết chương trình để thay đổi tuổi của hai học sinh, được khởi tạo trong hàm tạo mặc định (hàm tạo không có đối số) là 0 thành 22 cho học sinh đầu tiên và 20 cho học sinh thứ hai và hiển thị dữ liệu dưới dạng đầu ra.
See the following code example.
#include <iostream>
using namespace std;
class student
{
public:
student() /*Creating a constructor with 2 parameter*/
{
cout << "Class and objects successfully created and age is initialized to 0 for both the students" << endl;
int age_1 = 0;
int age_2 = 0;
cout << "\nAge of student 1 after initialization= " << age_1 << endl;
cout << "Age of student 2 after initialization= " << age_2 << endl;
}
student(int age_1, int age_2) /*Creating a constructor with 1 parameter*/
{
cout << "\nAge of 1st student after changing the initialized value = " << age_1 << endl;
cout << "Age of 2nd student after changing the initialized value = " << age_2;
}
};
int main()
{
student obj1;
student obj2(22, 20); /*Assigning the values to the age variables of the student*/
}
See the following output.
You can also check out the Destructors in C++ article in this blog.
That’s it for constructor overloading in c++.
Link: https://appdividend.com/2022/01/29/constructor-overloading-in-cpp/
#c #cpluplus
1660561380
Avant de comprendre la surcharge des constructeurs, nous devons d'abord comprendre ce que sont les constructeurs. Les constructeurs sont des méthodes uniques appelées automatiquement lorsque nous créons un objet de classe. L'objectif principal des constructeurs est d'initialiser les données membres du nouvel objet .
Dans la surcharge de constructeur C++, nous pouvons avoir plusieurs constructeurs dans la classe avec le même nom, tant que chacun a une liste d'arguments différente. C'est assez similaire à la surcharge de fonctions .
Il existe trois types de constructeurs :
Venons-en maintenant à la surcharge du constructeur , nous avons plus d'un constructeur présent dans la classe, mais ils diffèrent par le nombre d'arguments présents.
Propriétés des constructeurs à garder à l'esprit lors de la surcharge d'un constructeur :
Lorsque nous ajoutons plusieurs constructeurs à une classe, nous l'appelons plusieurs constructeurs.
La surcharge de constructeur est très similaire à la surcharge de fonction .
Constructeur surchargeant le changement du nombre d'arguments dans la liste de paramètres actuelle du constructeur. Par conséquent, nous pouvons utiliser des constructeurs de la même classe à des fins différentes.
Supposons que nous devions générer un lot pour un ensemble particulier d'étudiants, que ce soit 500 étudiants dans un seul lot, et que la variable class_no est définie sur 9 pour tous les étudiants car ils sont tous dans la classe 9.
Il sera très fastidieux de nourrir la variable class_no 500 fois égale à 9 pour tous les étudiants. C'est pourquoi nous utilisons des constructeurs. Nous créons un objet de la classe et passons la variable class_no comme argument du constructeur pour définir la valeur de class_no = 9 pour tous les 500 étudiants.
Consultez la syntaxe de code suivante.
class A
{
A()
{
body; //constructor with no parameter
}
A(int a, int b)
{
body; //constructor with 2 parameters
}
};
Exemple 1 : écrivez un programme pour surcharger deux constructeurs, un avec deux paramètres pour trouver l'aire du rectangle et le second avec un paramètre pour trouver l'aire du carré.
#include <iostream>
using namespace std;
class Area
{
public:
Area()
{
cout << "Class and object successfully created" << endl;
}
Area(int length, int breadth) /*Creating a constructor with 2 parameter*/
{
cout << "Area of the rectangle =" << length * breadth << endl;
}
Area(int side) /*Creating a constructor with 1 parameter*/
{
cout << "Area of the square = " << side * side << endl;
}
};
int main()
{
Area obj1;
Area obj2(5, 6); /*Initializing the value of length=5 and breadth=6*/
Area obj3(5); /*Initializing the value of side of square=5*/
return (0);
}
Voir la sortie suivante.
Exemple 2 :
Écrivez un programme pour changer l'âge de deux étudiants, qui sont initialisés dans le constructeur par défaut (constructeur sans arguments) de 0 à 22 pour le premier étudiant et 20 pour le deuxième étudiant, et affichez les données en sortie.
Voir l'exemple de code suivant.
#include <iostream>
using namespace std;
class student
{
public:
student() /*Creating a constructor with 2 parameter*/
{
cout << "Class and objects successfully created and age is initialized to 0 for both the students" << endl;
int age_1 = 0;
int age_2 = 0;
cout << "\nAge of student 1 after initialization= " << age_1 << endl;
cout << "Age of student 2 after initialization= " << age_2 << endl;
}
student(int age_1, int age_2) /*Creating a constructor with 1 parameter*/
{
cout << "\nAge of 1st student after changing the initialized value = " << age_1 << endl;
cout << "Age of 2nd student after changing the initialized value = " << age_2;
}
};
int main()
{
student obj1;
student obj2(22, 20); /*Assigning the values to the age variables of the student*/
}
Voir la sortie suivante.
Vous pouvez également consulter l' article Destructors in C++ dans ce blog.
C'est tout pour la surcharge du constructeur en c++.
Lien : https://appdividend.com/2022/01/29/constructor-overloading-in-cpp/
#c #cpluplus
1660554120
Прежде чем понять перегрузку конструктора, нам сначала нужно понять, что такое конструкторы. Конструкторы — это уникальные методы, вызываемые автоматически при создании объекта класса. Основная цель конструкторов — инициализировать элементы данных нового объекта .
При перегрузке конструктора C++ у нас может быть более одного конструктора в классе с одним и тем же именем, если каждый из них имеет другой список аргументов. Это очень похоже на перегрузку функций .
Существует три типа конструкторов:
Теперь, переходя к перегрузке конструктора , у нас есть более одного конструктора в классе, но они отличаются количеством присутствующих аргументов.
Свойства конструкторов, которые следует учитывать при перегрузке конструктора:
Когда мы добавляем в класс более одного конструктора, мы называем его несколькими конструкторами.
Перегрузка конструктора очень похожа на перегрузку функций .
Конструктор перегружает изменение количества аргументов в текущем списке параметров конструктора. Следовательно, мы можем использовать конструкторы одного класса для разных целей.
Предположим, нам нужно сгенерировать пакет для определенного набора учащихся, будь то 500 учеников в одном пакете, а для переменной class_no установлено значение 9 для всех учеников, поскольку все они учатся в классе 9.
Будет очень утомительно кормить переменную class_no 500 раз равной 9 для всех учеников. Вот почему мы используем конструкторы. Мы создаем объект класса и передаем переменную class_no в качестве аргумента конструктора, чтобы установить значение class_no = 9 для всех 500 учеников.
См. следующий синтаксис кода.
class A
{
A()
{
body; //constructor with no parameter
}
A(int a, int b)
{
body; //constructor with 2 parameters
}
};
Пример 1. Напишите программу для перегрузки двух конструкторов: один с двумя параметрами для нахождения площади прямоугольника, а второй с одним параметром для нахождения площади квадрата.
#include <iostream>
using namespace std;
class Area
{
public:
Area()
{
cout << "Class and object successfully created" << endl;
}
Area(int length, int breadth) /*Creating a constructor with 2 parameter*/
{
cout << "Area of the rectangle =" << length * breadth << endl;
}
Area(int side) /*Creating a constructor with 1 parameter*/
{
cout << "Area of the square = " << side * side << endl;
}
};
int main()
{
Area obj1;
Area obj2(5, 6); /*Initializing the value of length=5 and breadth=6*/
Area obj3(5); /*Initializing the value of side of square=5*/
return (0);
}
См. следующий вывод.
Пример 2:
Напишите программу для изменения возраста двух учеников, которые инициализируются в конструкторе по умолчанию (конструктор без аргументов) от 0 до 22 для первого ученика и 20 для второго ученика, и отобразите данные в качестве вывода.
См. следующий пример кода.
#include <iostream>
using namespace std;
class student
{
public:
student() /*Creating a constructor with 2 parameter*/
{
cout << "Class and objects successfully created and age is initialized to 0 for both the students" << endl;
int age_1 = 0;
int age_2 = 0;
cout << "\nAge of student 1 after initialization= " << age_1 << endl;
cout << "Age of student 2 after initialization= " << age_2 << endl;
}
student(int age_1, int age_2) /*Creating a constructor with 1 parameter*/
{
cout << "\nAge of 1st student after changing the initialized value = " << age_1 << endl;
cout << "Age of 2nd student after changing the initialized value = " << age_2;
}
};
int main()
{
student obj1;
student obj2(22, 20); /*Assigning the values to the age variables of the student*/
}
См. следующий вывод.
Вы также можете ознакомиться со статьей о деструкторах в C++ в этом блоге.
Вот и все, что касается перегрузки конструктора в С++.
Ссылка: https://appdividend.com/2022/01/29/constructor-overloading-in-cpp/
#c #cplusplus
1660546786
在了解構造函數重載之前,我們首先需要了解構造函數是什麼。構造函數是我們創建類對象時自動調用的唯一方法。構造函數的主要目的是初始化新對象的數據成員。
在 C++ 構造函數重載中,我們可以在類中擁有多個同名的構造函數,只要每個構造函數具有不同的參數列表即可。它與函數重載非常相似。
構造函數分為三種:
現在來到構造函數重載,我們在類中存在多個構造函數,但它們的不同在於存在的參數數量。
重載構造函數時要記住的構造函數屬性:
當我們向一個類添加多個構造函數時,我們稱其為多個構造函數。
構造函數重載與函數重載非常相似。
構造函數重載改變構造函數當前參數列表中的參數數量。因此,我們可以將同一類的構造函數用於不同的目的。
假設我們必須為一組特定的學生生成一個批次,一個批次中有 500 名學生,並且變量 class_no 為所有學生設置為 9,因為他們都在第 9 班。
為所有學生提供 500 次等於 9 的 class_no 變量將非常乏味。這就是我們使用構造函數的原因。我們創建一個類的對象,並將 class_no 變量作為構造函數的參數傳遞給所有 500 名學生的 class_no = 9 的值。
請參閱以下代碼語法。
class A
{
A()
{
body; //constructor with no parameter
}
A(int a, int b)
{
body; //constructor with 2 parameters
}
};
例1:編寫一個程序重載兩個構造函數,一個帶兩個參數求矩形的面積,第二個帶一個參數求正方形的面積。
#include <iostream>
using namespace std;
class Area
{
public:
Area()
{
cout << "Class and object successfully created" << endl;
}
Area(int length, int breadth) /*Creating a constructor with 2 parameter*/
{
cout << "Area of the rectangle =" << length * breadth << endl;
}
Area(int side) /*Creating a constructor with 1 parameter*/
{
cout << "Area of the square = " << side * side << endl;
}
};
int main()
{
Area obj1;
Area obj2(5, 6); /*Initializing the value of length=5 and breadth=6*/
Area obj3(5); /*Initializing the value of side of square=5*/
return (0);
}
請參閱以下輸出。
示例 2:
編寫一個程序來改變兩個學生的年齡,在默認構造函數(沒有參數的構造函數)中初始化為第一個學生的 0 到 22,第二個學生的 20,並將數據顯示為輸出。
請參閱以下代碼示例。
#include <iostream>
using namespace std;
class student
{
public:
student() /*Creating a constructor with 2 parameter*/
{
cout << "Class and objects successfully created and age is initialized to 0 for both the students" << endl;
int age_1 = 0;
int age_2 = 0;
cout << "\nAge of student 1 after initialization= " << age_1 << endl;
cout << "Age of student 2 after initialization= " << age_2 << endl;
}
student(int age_1, int age_2) /*Creating a constructor with 1 parameter*/
{
cout << "\nAge of 1st student after changing the initialized value = " << age_1 << endl;
cout << "Age of 2nd student after changing the initialized value = " << age_2;
}
};
int main()
{
student obj1;
student obj2(22, 20); /*Assigning the values to the age variables of the student*/
}
請參閱以下輸出。
您還可以查看此博客中的 C++ 中的析構函數一文。
這就是 C++ 中的構造函數重載。
鏈接:https ://appdividend.com/2022/01/29/constructor-overloading-in-cpp/
#c #cphusplus
1660304640
This is the MicroPython project, which aims to put an implementation of Python 3.x on microcontrollers and small embedded systems. You can find the official website at micropython.org.
WARNING: this project is in beta stage and is subject to changes of the code-base, including project-wide name changes and API changes.
MicroPython implements the entire Python 3.4 syntax (including exceptions, with
, yield from
, etc., and additionally async
/await
keywords from Python 3.5). The following core datatypes are provided: str
(including basic Unicode support), bytes
, bytearray
, tuple
, list
, dict
, set
, frozenset
, array.array
, collections.namedtuple
, classes and instances. Builtin modules include sys
, time
, and struct
, etc. Select ports have support for _thread
module (multithreading). Note that only a subset of Python 3 functionality is implemented for the data types and modules.
MicroPython can execute scripts in textual source form or from precompiled bytecode, in both cases either from an on-device filesystem or "frozen" into the MicroPython executable.
See the repository http://github.com/micropython/pyboard for the MicroPython board (PyBoard), the officially supported reference electronic circuit board.
Major components in this repository:
Additional components:
The subdirectories above may include READMEs with additional info.
"make" is used to build the components, or "gmake" on BSD-based systems. You will also need bash, gcc, and Python 3.3+ available as the command python3
(if your system only has Python 2.7 then invoke make with the additional option PYTHON=python2
).
Most ports require the MicroPython cross-compiler to be built first. This program, called mpy-cross, is used to pre-compile Python scripts to .mpy files which can then be included (frozen) into the firmware/executable for a port. To build mpy-cross use:
$ cd mpy-cross
$ make
The "unix" port requires a standard Unix environment with gcc and GNU make. x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well as ARM and MIPS. Making full-featured port to another architecture requires writing some assembly code for the exception handling and garbage collection. Alternatively, fallback implementation based on setjmp/longjmp can be used.
To build (see section below for required dependencies):
$ cd ports/unix
$ make submodules
$ make
Then to give it a try:
$ ./micropython
>>> list(5 * x + y for x in range(10) for y in [4, 2, 1])
Use CTRL-D
(i.e. EOF) to exit the shell. Learn about command-line options (in particular, how to increase heap size which may be needed for larger applications):
$ ./micropython -h
Run complete testsuite:
$ make test
Unix version comes with a builtin package manager called upip, e.g.:
$ ./micropython -m upip install micropython-pystone
$ ./micropython -m pystone
Browse available modules on PyPI. Standard library modules come from micropython-lib project.
Building MicroPython ports may require some dependencies installed.
For Unix port, libffi
library and pkg-config
tool are required. On Debian/Ubuntu/Mint derivative Linux distros, install build-essential
(includes toolchain and make), libffi-dev
, and pkg-config
packages.
Other dependencies can be built together with MicroPython. This may be required to enable extra features or capabilities, and in recent versions of MicroPython, these may be enabled by default. To build these additional dependencies, in the port directory you're interested in (e.g. ports/unix/
) first execute:
$ make submodules
This will fetch all the relevant git submodules (sub repositories) that the port needs. Use the same command to get the latest versions of submodules as they are updated from time to time. After that execute:
$ make deplibs
This will build all available dependencies (regardless whether they are used or not). If you intend to build MicroPython with additional options (like cross-compiling), the same set of options should be passed to make deplibs
. To actually enable/disable use of dependencies, edit ports/unix/mpconfigport.mk
file, which has inline descriptions of the options. For example, to build SSL module (required for upip
tool described above, and so enabled by default), MICROPY_PY_USSL
should be set to 1.
For some ports, building required dependences is transparent, and happens automatically. But they still need to be fetched with the make submodules
command.
The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils, arm-none-eabi-gcc and arm-none-eabi-newlib packages. Otherwise, try here: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
To build:
$ cd ports/stm32
$ make submodules
$ make
You then need to get your board into DFU mode. On the pyboard, connect the 3V3 pin to the P1/DFU pin with a wire (on PYBv1.0 they are next to each other on the bottom left of the board, second row from the bottom).
Then to flash the code via USB DFU to your device:
$ make deploy
This will use the included tools/pydfu.py
script. If flashing the firmware does not work it may be because you don't have the correct permissions, and need to use sudo make deploy
. See the README.md file in the ports/stm32/ directory for further details.
MicroPython is an open-source project and welcomes contributions. To be productive, please be sure to follow the Contributors' Guidelines and the Code Conventions. Note that MicroPython is licenced under the MIT license, and all contributions should follow this license.
Author: micropython
Source code: https://github.com/micropython/micropython
License: View license
#python #c
1660297920
Fantom Ledger Nano S and/or Ledger Nano X hardware wallet and secure key storage application.
Please make sure you have the toolchain set and ready, see Getting Started documentation on Ledger Documentation Hub.
Before you try to load the app to your Ledger device, make sure you have the device updated to the most recent firmware. If on Linux, you may need to setup udev
rules for your device to be available in the system.
Ledger provides automated udevsetup script. Enter the following command to automatically add the rules and reload udev:
wget -q -O - https://raw.githubusercontent.com/LedgerHQ/udev-rules/master/add_udev_rules.sh | sudo bash
Don't forget to reload udev rules in system's shell to load the changes.
udevadm control --reload
Following article can help you fix your connection problems.
make load
Download details:
Author: Fantom-foundation
Source code: https://github.com/Fantom-foundation/fantom-ledger
License: MIT license
#fantom #blockchain #c #python
1659784168
Ceci est le deuxième article d'une série en deux parties sur l'affichage des informations du débogueur GNU (GDB) dans une fenêtre personnalisée pendant que vous déboguez un programme C ou C++ . Le premier article présentait l'interface utilisateur textuelle (TUI) de GDB et montrait comment créer une fenêtre à l'aide de l' API Python . Cette deuxième partie termine le programme d'exemple en affichant les valeurs de la liste d'historique de GDB.
Pour commencer, ajoutez une ligne supplémentaire dans la __init__
méthode que vous avez créée dans l'article précédent :
self._next_history_index = 1
La _next_history_index
variable sera utilisée pour récupérer les valeurs de la liste d'historique de GDB. La valeur commence à 1 car la première valeur de l'historique des valeurs de GDB est numérotée 1. À chaque itération d'une boucle que vous écrirez, la _next_history_index
variable représentera le prochain index que vous devez extraire de l'historique des valeurs de GDB.
Ensuite, ajoutez deux nouvelles méthodes à la history_window
classe, qui se chargeront de récupérer les valeurs de la liste d'historique :
def _add_next_history_value(self):
try:
value = gdb.history(self._next_history_index)
string = value.format_string(pretty_arrays=False,
pretty_structs=False)
string = "$%d = %s" % (self._next_history_index,
re.sub(r"\\s*\n\\s*", " ", string))
self._lines.append(string)
self._next_history_index += 1
except:
return False
return True
def _update(self):
while self._add_next_history_value():
pass
La _add_next_history_value
méthode essaie d'extraire l'élément suivant de l'historique des valeurs de GDB. Si cela réussit, la valeur est convertie en une chaîne à une seule ligne et ajoutée à la _lines
liste. Enfin, la méthode incrémente le _next_history_index
.
Pour que ce didacticiel reste simple, la méthode convertit chaque valeur à représenter en une seule ligne. Cette conversion utilise l' re.sub
appel, qui remplace tous les caractères de retour à la ligne par un espace unique à l'aide d'une expression régulière. Pour activer l'utilisation d'une expression régulière, vous devez ajouter la ligne suivante en haut du history.py
fichier :
import re
La _update
méthode appelle juste _add_next_history_value
jusqu'à ce que toutes les valeurs d'historique aient été traitées.
Enfin, vous devez appeler _update
à deux endroits.
Tout d'abord, appelez _update
depuis la __init__
méthode pour vous assurer que, dès que votre fenêtre est créée, toutes les valeurs d'historique existantes sont chargées dans la _lines
liste. La __init__
méthode complète devrait maintenant ressembler à ceci :
def __init__(self, tui_window):
self._tui_window = tui_window
self._tui_window.title = 'Value History'
self._before_prompt_listener = lambda : self._before_prompt()
gdb.events.before_prompt.connect(self._before_prompt_listener)
self._lines = []
self._next_history_index = 1
self._update()
Ensuite, ajoutez un appel à _update
partir de la _before_prompt
méthode, en remplaçant la ligne de débogage existante. La _before_prompt
méthode complète devrait maintenant ressembler à ceci :
def _before_prompt(self):
self._update()
self.render()
Et avec ces modifications, vous disposez d'une fenêtre d'historique de travail de base. Redémarrez GDB à l'aide de la ligne de commande :
gdb -ex 'source history.py' \
-ex 'tui new-layout example_1 history 1 cmd 1 status 1' \
-ex 'layout example_1'
La figure 1 montre à quoi la fenêtre devrait ressembler en action après avoir entré quelques commandes dans la fenêtre de commande :
Figure 1 : L'écran Historique des valeurs affiche dynamiquement les valeurs dans GDB.
Ce que vous avez jusqu'à présent est génial. Mais il y a un problème. Une fois que la fenêtre reçoit un grand nombre de valeurs d'historique, les premières sont perdues en haut de la fenêtre. Ce serait formidable si vous pouviez revenir en arrière pour afficher les valeurs précédentes. Ce sera donc la dernière fonctionnalité que vous ajouterez dans ce tutoriel.
Mais d'abord, vous devez retravailler un peu le code pour faciliter l'ajout de la prise en charge du défilement.
Ajoutez les méthodes suivantes à votre history_window
classe :
def _history_count(self):
return self._next_history_index - 1
def _display_start(self):
return self._max_history_start()
def _max_history_start(self):
count = self._history_count()
height = self._tui_window.height
return max(1, count - height + 1)
La _history_count
méthode renvoie le nombre d'éléments d'historique qui ont été chargés dans la _lines
variable.
La _display_start
méthode renvoie l'indice de la première valeur d'historique qui doit être affichée dans la fenêtre. Vous ne faites pas encore grand-chose ici, mais vous étendrez la méthode plus tard.
Enfin, _max_history_start
renvoie l'index de valeur d'historique à partir duquel le code doit commencer (c'est-à-dire la valeur affichée en haut de la fenêtre) afin que la dernière valeur d'historique connue apparaisse également dans la fenêtre (en bas).
Enfin, revenez à la ligne suivante qui se trouve actuellement dans votre render
méthode :
lines = self._lines[-height:]
Remplacez cette ligne par la suivante :
start = self._display_start() - 1
end = start + height
lines = self._lines[start:end]
La fonction imprime maintenant le height
nombre de lignes à partir de _display_start()
. Le - 1
est obligatoire car _display_start()
renvoie un index d'historique, qui compte à partir de 1, alors qu'il _lines
s'agit d'une liste Python, indexée à partir de 0.
Après ces changements, le history_window
devrait fonctionner comme avant, et vous êtes maintenant prêt pour la dernière partie de ce didacticiel.
Vous devez apporter trois autres modifications mineures pour ajouter la prise en charge du défilement.
Tout d'abord, ajoutez la ligne suivante à la __init__
méthode avant l'appel àself._update()
:
self._vscroll_start = None
Cette variable agit comme un marqueur pour indiquer si la fenêtre défile. Lorsqu'il est défini sur None
, la fenêtre ne défile pas. Par conséquent, les nouvelles valeurs doivent être ajoutées à la fin de la fenêtre et les anciennes valeurs doivent disparaître du haut. En revanche, lorsque la variable est définie sur un nombre entier, elle indique à quelle valeur d'historique revenir en arrière. La fenêtre affichera alors toujours les éléments à partir de cet index.
Ensuite, réécrivez la _dispay_start
méthode comme ceci :
def _display_start(self):
if self._vscroll_start is None:
start = self._max_history_start()
else:
start = self._vscroll_start
return start
Maintenant, si _vscroll_start
a été défini, la fenêtre le traite comme l'index pour démarrer l'affichage. Si _vscroll_start
n'est pas défini, la méthode fait les choses exactement comme avant.
Enfin, ajoutez la vcsroll
méthode suivante à votre history_window
classe :
def vscroll(self, num):
start = self._display_start()
start += num
start = max(1, start + num)
max_start = self._max_history_start()
if start >= max_start:
self._vscroll_start = None
else:
self._vscroll_start = start
self.render()
L' num
argument indique le nombre de lignes par lequel GDB souhaite faire défiler le contenu de la fenêtre. Appuyer sur les touches fléchées vers le haut ou vers le bas entraîne un changement de ligne unique, tandis que les touches PageUp ou PageDown entraînent un changement plus important en fonction de la taille actuelle de la fenêtre.
La vscroll
méthode détermine l'index d'historique pour la première ligne actuelle de la fenêtre et ajuste cet index par la valeur de num
. La méthode limite cette valeur à certaines limites raisonnables : ainsi, vous ne pouvez pas revenir en arrière avant l'index 1 (le premier index de l'historique GDB), ni faire défiler vers l'avant au-delà de la valeur de max_start
. Cette variable stocke l'index à partir duquel vous pouvez commencer à imprimer des éléments tout en récupérant le dernier élément de l'historique affiché dans la fenêtre.
Enfin, si l'utilisateur a fait défiler jusqu'à la valeur dans max_start
, la méthode est définie _vscroll_start
sur None
. Cela indique qu'à mesure que de nouvelles valeurs d'historique apparaissent, elles doivent être ajoutées au bas de la fenêtre, repoussant les anciennes valeurs vers le haut.
Et avec cela, votre fenêtre est complète. Vous pouvez revenir en arrière pour afficher toutes les anciennes valeurs d'historique et avancer à nouveau pour afficher les dernières valeurs d'historique.
Lien : https://developers.redhat.com/articles/2022/08/04/display-dynamic-content-gdb-custom-window#
#gdb #python #c
1659775529
Это вторая статья из серии из двух частей, посвященной отображению информации из отладчика GNU (GDB) в пользовательском окне во время отладки программы на C или C++ . В первой статье был представлен текстовый пользовательский интерфейс GDB (TUI) и показано, как создать окно с помощью Python API. Эта вторая часть завершает пример программы, отображая значения из списка истории GDB.
Для начала добавьте дополнительную строку в __init__
метод, который вы создали в предыдущей статье:
self._next_history_index = 1
Переменная _next_history_index
будет использоваться для получения значений из списка истории GDB. Значение начинается с 1, потому что первое значение в истории значений GDB имеет номер 1. На каждой итерации цикла, который вы будете писать, _next_history_index
переменная будет представлять следующий индекс, который вам нужно получить из истории значений GDB.
Затем добавьте в класс два новых метода history_window
, которые будут выполнять работу по извлечению значений из списка истории:
def _add_next_history_value(self):
try:
value = gdb.history(self._next_history_index)
string = value.format_string(pretty_arrays=False,
pretty_structs=False)
string = "$%d = %s" % (self._next_history_index,
re.sub(r"\\s*\n\\s*", " ", string))
self._lines.append(string)
self._next_history_index += 1
except:
return False
return True
def _update(self):
while self._add_next_history_value():
pass
Метод _add_next_history_value
пытается получить следующий элемент из истории значений GDB. В случае успеха значение преобразуется в однострочную строку и добавляется в _lines
список. Наконец, метод увеличивает _next_history_index
.
Чтобы сделать этот учебник простым, метод преобразует каждое значение для представления в одну строку. Это преобразование использует re.sub
вызов, который заменяет любые символы новой строки одним пробелом с использованием регулярного выражения. Чтобы включить использование регулярного выражения, вам нужно добавить следующую строку в начало history.py
файла:
import re
Метод _update
просто вызывается _add_next_history_value
до тех пор, пока не будут обработаны все значения истории.
Наконец, вам нужно позвонить _update
в двух местах.
Во- первых, вызовите _update
метод __init__
, чтобы убедиться, что, как только ваше окно будет создано, все существующие значения истории будут загружены в _lines
список. Полный __init__
метод теперь должен выглядеть так:
def __init__(self, tui_window):
self._tui_window = tui_window
self._tui_window.title = 'Value History'
self._before_prompt_listener = lambda : self._before_prompt()
gdb.events.before_prompt.connect(self._before_prompt_listener)
self._lines = []
self._next_history_index = 1
self._update()
Затем добавьте вызов _update
из _before_prompt
метода, заменив существующую строку отладки. Полный _before_prompt
метод теперь должен выглядеть так:
def _before_prompt(self):
self._update()
self.render()
И с этими изменениями у вас есть базовое рабочее окно истории. Перезапустите GDB с помощью командной строки:
gdb -ex 'source history.py' \
-ex 'tui new-layout example_1 history 1 cmd 1 status 1' \
-ex 'layout example_1'
На рис. 1 показано, как должно выглядеть окно в действии после ввода нескольких команд в командном окне:
Рисунок 1: Экран Value History динамически отображает значения в GDB.
То, что у вас есть до сих пор, прекрасно. Но есть одна проблема. Как только окно получает много значений истории, более ранние теряются в верхней части окна. Было бы здорово, если бы вы могли прокрутить назад, чтобы просмотреть более ранние значения. Так что это будет последняя функция, которую вы добавите в этом уроке.
Но сначала нужно немного переработать код, чтобы проще было добавить поддержку прокрутки.
history_window
Добавьте в свой класс следующие методы :
def _history_count(self):
return self._next_history_index - 1
def _display_start(self):
return self._max_history_start()
def _max_history_start(self):
count = self._history_count()
height = self._tui_window.height
return max(1, count - height + 1)
Метод _history_count
возвращает количество элементов истории, которые были загружены в _lines
переменную.
Метод _display_start
возвращает индекс первого значения истории, которое должно отображаться в окне. Здесь вы еще ничего не делаете, но позже расширите метод.
Наконец, _max_history_start
возвращает индекс значения истории, с которого должен начинаться код (то есть значение, отображаемое в верхней части окна), чтобы последнее известное значение истории также отображалось в окне (внизу).
Наконец, вернитесь к следующей строке, которая в данный момент находится в вашем render
методе:
lines = self._lines[-height:]
Замените эту строку следующей:
start = self._display_start() - 1
end = start + height
lines = self._lines[start:end]
Теперь функция печатает height
количество строк, начиная с _display_start()
. - 1
Требуется, потому что _display_start()
возвращает индекс истории, который отсчитывается от 1, тогда как это _lines
список Python, индексируемый от 0.
После этих изменений все history_window
должно работать так же, как и раньше, и теперь вы готовы к заключительной части этого руководства.
Вам нужно внести еще три небольших изменения, чтобы добавить поддержку прокрутки.
Во-первых, добавьте следующую строку в __init__
метод перед вызовом self._update()
:
self._vscroll_start = None
Эта переменная действует как маркер, указывающий, прокручивается ли окно. Если установлено значение None
, окно не прокручивается. Поэтому новые значения должны добавляться в конец окна, а старые значения должны исчезать сверху. Напротив, когда для переменной задано целое число, оно указывает, к какому значению истории следует вернуться. В этом случае в окне всегда будут отображаться элементы, начиная с этого индекса.
Далее перепишите _dispay_start
метод следующим образом:
def _display_start(self):
if self._vscroll_start is None:
start = self._max_history_start()
else:
start = self._vscroll_start
return start
Теперь, если _vscroll_start
он был установлен, окно рассматривает его как индекс для начала отображения. Если _vscroll_start
не установлено, метод работает точно так же, как и раньше.
Наконец, добавьте в свой класс следующий vcsroll
метод :history_window
def vscroll(self, num):
start = self._display_start()
start += num
start = max(1, start + num)
max_start = self._max_history_start()
if start >= max_start:
self._vscroll_start = None
else:
self._vscroll_start = start
self.render()
Аргумент num
указывает количество строк, на которое GDB хотел бы прокрутить содержимое окна. Нажатие клавиш со стрелками вверх или вниз приводит к изменению одной строки, тогда как клавиши PageUp или PageDown приводят к большему изменению в зависимости от текущего размера окна.
Метод vscroll
вычисляет индекс истории для текущей первой строки окна и корректирует этот индекс на значение num
. Метод ограничивает это значение некоторыми разумными пределами: таким образом, вы не можете прокручивать назад до индекса 1 (первого индекса истории GDB) и не должны прокручивать вперед за значение max_start
. Эта переменная хранит индекс, с которого вы можете начать печать элементов и при этом получить последний элемент из истории, показанной в окне.
Наконец, если пользователь прокрутил до значения в max_start
, метод устанавливает _vscroll_start
значение None
. Это указывает на то, что по мере появления новых значений истории их следует добавлять в нижнюю часть окна, вытесняя старые значения из верхней части.
И на этом ваше окно готово. Вы можете прокрутить назад, чтобы просмотреть все старые значения истории, и снова перемотать вперед, чтобы просмотреть последние значения истории.
Ссылка: https://developers.redhat.com/articles/2022/08/04/display-dynamic-content-gdb-custom-window#
#gdb #python #c
1659768248
Trong loạt bài gồm hai phần về việc hiển thị thông tin từ Trình gỡ lỗi GNU (GDB) trong cửa sổ tùy chỉnh khi bạn đang gỡ lỗi chương trình C hoặc C ++ .Phần này kết thúc chương trình ví dụ bằng cách hiển thị các giá trị từ danh sách lịch sử của GDB.
Để bắt đầu, hãy thêm một dòng bổ sung trong __init__
phương thức bạn đã tạo trong bài viết trước:
self._next_history_index = 1
Biến _next_history_index
sẽ được sử dụng để tìm nạp các giá trị từ danh sách lịch sử của GDB. Giá trị bắt đầu từ 1 vì giá trị đầu tiên trong lịch sử giá trị của GDB được đánh số 1. Tại mỗi lần lặp lại vòng lặp bạn sẽ viết, _next_history_index
biến sẽ đại diện cho chỉ mục tiếp theo mà bạn cần lấy từ lịch sử giá trị của GDB.
Tiếp theo, thêm hai phương thức mới vào history_window
lớp, phương thức này sẽ thực hiện công việc tìm nạp các giá trị từ danh sách lịch sử:
def _add_next_history_value(self):
try:
value = gdb.history(self._next_history_index)
string = value.format_string(pretty_arrays=False,
pretty_structs=False)
string = "$%d = %s" % (self._next_history_index,
re.sub(r"\\s*\n\\s*", " ", string))
self._lines.append(string)
self._next_history_index += 1
except:
return False
return True
def _update(self):
while self._add_next_history_value():
pass
Phương _add_next_history_value
thức cố gắng tìm nạp mục tiếp theo từ lịch sử giá trị của GDB. Nếu điều này thành công, giá trị sẽ được chuyển đổi thành chuỗi một dòng và được thêm vào _lines
danh sách. Cuối cùng, phương thức gia tăng _next_history_index
.
Để giữ cho hướng dẫn này đơn giản, phương pháp chuyển đổi mỗi giá trị được biểu diễn thành một dòng duy nhất. Chuyển đổi này sử dụng lệnh re.sub
gọi, thay thế bất kỳ ký tự dòng mới nào bằng một khoảng trắng duy nhất bằng cách sử dụng biểu thức chính quy. Để cho phép sử dụng một biểu thức chính quy, bạn cần thêm dòng sau vào đầu history.py
tệp:
import re
Phương _update
thức chỉ gọi _add_next_history_value
cho đến khi tất cả các giá trị lịch sử đã được xử lý.
Cuối cùng, bạn cần gọi điện _update
ở hai nơi.
Đầu tiên, hãy gọi _update
từ __init__
phương thức để đảm bảo rằng, ngay sau khi cửa sổ của bạn được tạo, tất cả các giá trị lịch sử hiện có đều được tải vào _lines
danh sách. Phương thức hoàn chỉnh __init__
bây giờ sẽ giống như sau:
def __init__(self, tui_window):
self._tui_window = tui_window
self._tui_window.title = 'Value History'
self._before_prompt_listener = lambda : self._before_prompt()
gdb.events.before_prompt.connect(self._before_prompt_listener)
self._lines = []
self._next_history_index = 1
self._update()
Tiếp theo, thêm một lệnh gọi đến _update
từ _before_prompt
phương thức, thay thế dòng gỡ lỗi hiện có. Phương thức đầy đủ _before_prompt
bây giờ sẽ giống như sau:
def _before_prompt(self):
self._update()
self.render()
Và với những thay đổi này, bạn có một cửa sổ lịch sử làm việc cơ bản. Khởi động lại GDB bằng dòng lệnh:
gdb -ex 'source history.py' \
-ex 'tui new-layout example_1 history 1 cmd 1 status 1' \
-ex 'layout example_1'
Hình 1 cho thấy cửa sổ sẽ trông như thế nào khi hoạt động sau khi nhập một vài lệnh vào cửa sổ lệnh:
Hình 1: Màn hình Lịch sử giá trị hiển thị động các giá trị trong GDB.
Những gì bạn có cho đến nay thật tuyệt vời. Nhưng có một vấn đề. Khi cửa sổ nhận được nhiều giá trị lịch sử, những giá trị trước đó sẽ bị mất ở đầu cửa sổ. Sẽ thật tuyệt nếu bạn có thể cuộn lại để xem các giá trị trước đó. Vì vậy, đây sẽ là tính năng cuối cùng bạn thêm vào trong hướng dẫn này.
Nhưng trước tiên, bạn cần phải làm lại mã một chút để có thể thêm hỗ trợ cuộn dễ dàng hơn.
Thêm các phương thức sau vào history_window
lớp của bạn:
def _history_count(self):
return self._next_history_index - 1
def _display_start(self):
return self._max_history_start()
def _max_history_start(self):
count = self._history_count()
height = self._tui_window.height
return max(1, count - height + 1)
Phương _history_count
thức trả về số lượng mục lịch sử đã được tải vào _lines
biến.
Phương _display_start
thức trả về chỉ mục của giá trị lịch sử đầu tiên sẽ được hiển thị trong cửa sổ. Bạn chưa làm gì nhiều ở đây, nhưng sẽ mở rộng phương pháp sau.
Cuối cùng, _max_history_start
trả về chỉ mục giá trị lịch sử mà mã sẽ bắt đầu từ đó (nghĩa là giá trị được hiển thị ở đầu cửa sổ) để giá trị lịch sử đã biết gần đây nhất cũng xuất hiện trong cửa sổ (ở dưới cùng).
Cuối cùng, quay lại dòng sau hiện có trong render
phương thức của bạn:
lines = self._lines[-height:]
Thay thế dòng đó bằng dòng sau:
start = self._display_start() - 1
end = start + height
lines = self._lines[start:end]
Hàm hiện đang in height
số dòng bắt đầu từ _display_start()
. Là - 1
bắt buộc vì _display_start()
trả về chỉ mục lịch sử, được tính từ 1, trong khi _lines
là danh sách Python, được lập chỉ mục từ 0.
Sau những thay đổi này, công history_window
cụ sẽ hoạt động giống như trước đây và bây giờ bạn đã sẵn sàng cho phần cuối cùng của hướng dẫn này.
Bạn cần thực hiện thêm ba thay đổi nhỏ để thêm hỗ trợ cuộn.
Đầu tiên, hãy thêm dòng sau vào __init__
phương thức trước lệnh gọi tới self._update()
:
self._vscroll_start = None
Biến này hoạt động như một điểm đánh dấu để cho biết cửa sổ có được cuộn hay không. Khi được đặt thành None
, cửa sổ không được cuộn. Do đó, các giá trị mới nên được thêm vào cuối cửa sổ và các giá trị cũ sẽ biến mất khỏi đầu cửa sổ. Ngược lại, khi biến được đặt thành số nguyên, nó cho biết giá trị lịch sử nào sẽ cuộn lại. Sau đó cửa sổ sẽ luôn hiển thị các mục bắt đầu từ chỉ mục đó.
Tiếp theo, viết lại _dispay_start
phương thức như sau:
def _display_start(self):
if self._vscroll_start is None:
start = self._max_history_start()
else:
start = self._vscroll_start
return start
Bây giờ, nếu _vscroll_start
đã được thiết lập, cửa sổ coi nó như một chỉ mục để bắt đầu hiển thị. Nếu _vscroll_start
không được đặt, phương thức sẽ thực hiện mọi việc chính xác như trước.
Cuối cùng, thêm vcsroll
phương thức sau vào history_window
lớp của bạn:
def vscroll(self, num):
start = self._display_start()
start += num
start = max(1, start + num)
max_start = self._max_history_start()
if start >= max_start:
self._vscroll_start = None
else:
self._vscroll_start = start
self.render()
Đối num
số cho biết số dòng mà GDB muốn cuộn nội dung cửa sổ. Nhấn các phím mũi tên lên hoặc xuống dẫn đến thay đổi một dòng, trong khi các phím PageUp hoặc PageDown dẫn đến thay đổi lớn hơn dựa trên kích thước hiện tại của cửa sổ.
Phương vscroll
pháp tìm ra chỉ mục lịch sử cho dòng đầu tiên hiện tại của cửa sổ và điều chỉnh chỉ mục này theo giá trị của num
. Phương thức này kẹp giá trị này vào một số giới hạn lành mạnh: do đó, bạn không thể cuộn lại trước chỉ mục 1 (chỉ mục lịch sử GDB đầu tiên), cũng như không nên cuộn về phía trước vượt quá giá trị của max_start
. Biến này lưu trữ chỉ mục mà từ đó bạn có thể bắt đầu in các mục và vẫn nhận được mục cuối cùng từ lịch sử hiển thị trong cửa sổ.
Cuối cùng, nếu người dùng đã cuộn xuống giá trị trong max_start
đó, phương thức sẽ đặt _vscroll_start
thành None
. Điều này cho thấy rằng khi các giá trị lịch sử mới xuất hiện, chúng sẽ được thêm vào cuối cửa sổ, đẩy các giá trị cũ hơn lên trên cùng.
Và với điều đó, cửa sổ của bạn đã hoàn thành. Bạn có thể cuộn lại để xem tất cả các giá trị lịch sử cũ và chuyển tiếp lần nữa để xem các giá trị lịch sử mới nhất.
Liên kết: https://developers.redhat.com/articles/2022/08/04/display-dynamic-content-gdb-custom-window#
#gdb #python #c
1659760882
這是關於在調試C 或 C++程序時在自定義窗口中顯示來自GNU 調試器(GDB) 的信息的兩部分系列文章中的第二篇。第一篇文章介紹了 GDB 的文本用戶界面 (TUI) 並展示瞭如何使用Python API 創建一個窗口。第二部分通過顯示 GDB 歷史列表中的值來完成示例程序。
__init__
首先,在您在上一篇文章中創建的方法中添加額外的一行:
self._next_history_index = 1
該_next_history_index
變量將用於從 GDB 的歷史列表中獲取值。該值從 1 開始,因為 GDB 的值歷史記錄中的第一個值編號為 1。在您將編寫的循環的每次迭代中,該_next_history_index
變量將代表您需要從 GDB 的值歷史記錄中獲取的下一個索引。
接下來,向history_window
該類添加兩個新方法,它們將完成從歷史列表中獲取值的工作:
def _add_next_history_value(self):
try:
value = gdb.history(self._next_history_index)
string = value.format_string(pretty_arrays=False,
pretty_structs=False)
string = "$%d = %s" % (self._next_history_index,
re.sub(r"\\s*\n\\s*", " ", string))
self._lines.append(string)
self._next_history_index += 1
except:
return False
return True
def _update(self):
while self._add_next_history_value():
pass
該_add_next_history_value
方法嘗試從 GDB 的值歷史記錄中獲取下一項。如果成功,則將值轉換為單行字符串並添加到_lines
列表中。最後,該方法遞增_next_history_index
.
為了使本教程保持簡單,該方法將要表示的每個值轉換為單行。此轉換使用re.sub
調用,它使用正則表達式將任何換行符替換為單個空格。要啟用正則表達式,您需要將以下行添加到history.py
文件頂部:
import re
該_update
方法只調用_add_next_history_value
,直到所有歷史記錄值都已處理完畢。
最後,你需要_update
在兩個地方調用。
首先,_update
從__init__
方法調用以確保在創建窗口後,所有現有歷史記錄值都加載到_lines
列表中。完整的__init__
方法現在應該如下所示:
def __init__(self, tui_window):
self._tui_window = tui_window
self._tui_window.title = 'Value History'
self._before_prompt_listener = lambda : self._before_prompt()
gdb.events.before_prompt.connect(self._before_prompt_listener)
self._lines = []
self._next_history_index = 1
self._update()
接下來,添加對_update
from_before_prompt
方法的調用,替換現有的調試行。完整的_before_prompt
方法現在應該如下所示:
def _before_prompt(self):
self._update()
self.render()
通過這些更改,您將擁有一個基本的工作歷史記錄窗口。使用命令行重啟 GDB:
gdb -ex 'source history.py' \
-ex 'tui new-layout example_1 history 1 cmd 1 status 1' \
-ex 'layout example_1'
圖 1 顯示了在命令窗口中輸入一些命令後窗口的實際效果:
圖 1:Value History 屏幕動態顯示 GDB 中的值。
到目前為止,您所擁有的很棒。但是有一個問題。一旦窗口獲得大量歷史值,較早的值就會從窗口頂部丟失。如果您可以向後滾動以查看較早的值,那就太好了。所以這將是您在本教程中添加的最後一個功能。
但首先,您需要稍微修改代碼以使其更容易添加滾動支持。
將以下方法添加到您的history_window
類中:
def _history_count(self):
return self._next_history_index - 1
def _display_start(self):
return self._max_history_start()
def _max_history_start(self):
count = self._history_count()
height = self._tui_window.height
return max(1, count - height + 1)
該_history_count
方法返回已加載到_lines
變量中的歷史項目數。
該_display_start
方法返回應該在窗口中顯示的第一個歷史值的索引。您在這裡還沒有做太多,但稍後會擴展該方法。
最後,_max_history_start
返回代碼應該開始的歷史值索引(即顯示在窗口頂部的值),以便最後一個已知的歷史值也出現在窗口中(底部)。
最後,返回到當前render
方法中的以下行:
lines = self._lines[-height:]
將該行替換為以下內容:
start = self._display_start() - 1
end = start + height
lines = self._lines[start:end]
該函數現在正在打印height
從 開始的行數_display_start()
。- 1
是必需的,因為_display_start()
它返回一個從 1 開始計數的歷史索引,而_lines
它是一個 Python 列表,從 0 開始索引。
在這些更改之後,history_window
應該可以像以前一樣工作,現在您已準備好學習本教程的最後一部分。
您需要再做三個小的更改來添加滾動支持。
__init__
首先,在調用 to 之前將以下行添加到方法中self._update()
:
self._vscroll_start = None
這個變量作為一個標記來指示窗口是否被滾動。當設置為None
時,窗口不滾動。因此,應將新值添加到窗口的末尾,而舊值應從頂部消失。相反,當變量設置為整數時,它指示要滾動回哪個歷史值。然後,該窗口將始終顯示從該索引開始的項目。
接下來,_dispay_start
像這樣重寫方法:
def _display_start(self):
if self._vscroll_start is None:
start = self._max_history_start()
else:
start = self._vscroll_start
return start
現在,如果_vscroll_start
已設置,則窗口將其視為開始顯示的索引。如果_vscroll_start
未設置,則該方法完全按照以前的方式執行操作。
最後,將以下vcsroll
方法添加到您的history_window
類中:
def vscroll(self, num):
start = self._display_start()
start += num
start = max(1, start + num)
max_start = self._max_history_start()
if start >= max_start:
self._vscroll_start = None
else:
self._vscroll_start = start
self.render()
該num
參數表示 GDB 想要滾動窗口內容的行數。按向上或向下箭頭鍵會導致單行更改,而 PageUp 或 PageDown 鍵會根據窗口的當前大小導致更大的更改。
該vscroll
方法計算窗口當前第一行的歷史索引,並通過 的值調整該索引num
。該方法將此值限制在一些合理的範圍內:因此,您不能在索引 1(第一個 GDB 歷史索引)之前向後滾動,也不應該向前滾動超出max_start
. 此變量存儲索引,您可以從該索引開始打印項目,並且仍然可以從窗口中顯示的歷史記錄中獲取最後一個項目。
最後,如果用戶向下滾動到 中的值max_start
,則該方法設置_vscroll_start
為None
。這表明當新的歷史值出現時,它們應該被添加到窗口的底部,將舊值從頂部推開。
這樣,您的窗口就完成了。您可以向後滾動以查看所有舊的歷史記錄值,然後再次向前滾動以查看最新的歷史記錄值。
鏈接:https ://developers.redhat.com/articles/2022/08/04/display-dynamic-content-gdb-custom-window#
#gdb #python #c
1659499020
Parse C headers
I wrote this Common Lisp code to parse preprocessed C headers and use that data to generate cffi code(inside macro). (I have had trouble using other peoples' code like the 'groveller')
There is also a Julia code outputter.(see note above) julia-src/
contains code that is autogenerated, and other code to help use Julia's features. Only some openGL stuff and SDL stuff is very usable at the moment. (The SDL stuff doesn't use the parser, just some basic hooks into it) See the julia-src/ readme for more.
As parser, the current status is 'maybe it works', at best, but for me it is very useful to not have to do stuff manually.(However there not seeming a good program/lib to get this data from include files kindah sucks..)
Of course multiple ways of doing things; getting an FFI using an include file could just be (ffi-using-include-file "include-file" :package-name ...other options..)
or some such. But i think it is better to have a file, firstly to 'memoize' the result so no parsing has to place in development, and secondly to guard against the possibility of suddenly the output changing subtilly or worries like that.. You keep the script at hand, and try only using that to change those files.
I do want to keep the automatedly created files completely automated and anything beyond that in separate files. Also any operations on how the FFI is done should be transparent..
Currently there is just a function to throw things out from being FFI-ed, structs, for instance, as not yet supported, and some #define
s because for instance in GL/gl.h
, @define APIENTRY extern
would give Julia an entry APIENTRY = extern
, which doesn't make sense. Problem of course is that the parser doesn't know if C's #define
s are values or not.
Uses some stuff like Alexandria, and some of my string stuff from j-basic. (notably j-string-utils:tokenize
), as usual.
:to-cffi
needs to make symbols in CFFI
:header-cffi
helps using the program to preprocess, as such it uses external-program.
I want to have structs accessible for Julia. Automatically make a creator of a struct and accessor.
Trying to get more stuff parsed and ffi'ed in /usr/include/
Convert to Julia entirely?
Everything is under GPLv3, license included under doc/
Note: i dont work on this anymore atm, i moved stuff still worked on to julia-ffi a parser is WIP there aswel.
Author: o-jasper
Source Code: https://github.com/o-jasper/parse-c-header
License: GPLv3
1659491460
Julia ffi and C parser for generating it, and some various utilities.
This project contains:
This project also contains a utility lib. Some of which may be better off from a standard lib/more standard way to do it.
Everything specifically autogenerated is under autoffi/
, not everything works (or is complete there) there.(GL works pretty well)
Currently all the stuff in autoffi/
is completely analogous to the C interface. Some extra stuff is added outside of that directory.
To use, first compile some stuff within with make
(though not all of them need it)
Then edit ~/.juliarc.jl
and add (NOTE: it used to be /src/julia-src/
)
push(LOAD_PATH, "$(path_julia_ffi)/")
Then things can be loaded with paths originating from that.(hopefully)
Currently you have to run it as julia -L ~/.juliarc.jl
TODO is use the modules, and figure how to load things correctly..
Everything analogous to C works. I have yet to find any problem with autoffi/gl.j
. ffi_extra/gl_util.j
adds some useful functions, and overloaded version of the C functions (Note: glcolor
does not use glcolorb
for integers; it would be confusing)
It also adds stuff to make @with
work;(it needs the no_longer_with
method) so @with primitive() begin ... end
and @with pushed_matrix() ...
works.
bad_sdl_utils
needs make
to be run from it's directory. Also the readme in that directory lists the functions in there.
Note that this currently does not at all use the autoffi stuff, but you can catch most events.
autoffi/glu.j
not at all tested yet, autoffi/acpi.j
lacks a function to create the structs and look at its items. I want to add autogenerators for those. Note that then those parts aren't analogous to the C interface, and also maybe Julia will/has already increased support for FFIing those..
TODO
Author: o-jasper
Source Code: https://github.com/o-jasper/julia-ffi
License: MIT license
1658944140
Game networking is a subset of computer networking that commonly covers transport protocols, data replication, entity synchronization, lag compensation, client-side prediction, server reconciliation, interest management, bandwidth optimization, physics rollback/fastforward simulation, anti-cheating and many other areas involved in multiplayer online game development.
Please feel free to contribute with your awesome resource as well, thank you!
Quick Jump: Articles - Talks - Libraries - Tools
Download details:
Author: ThusWroteNomad
Source code: https://github.com/ThusWroteNomad/GameNetworkingResources
License:
#unity #gamedev #c
1658210400
ParaMonte: Plain Powerful Parallel Monte Carlo Library
ParaMonte is a serial/parallel library of Monte Carlo routines for sampling mathematical objective functions of arbitrary-dimensions, in particular, the posterior distributions of Bayesian models in data science, Machine Learning, and scientific inference, with the design goal of unifying the automation (of Monte Carlo simulations), user-friendliness (of the library), accessibility (from multiple programming environments), high-performance (at runtime), and scalability (across many parallel processors).
For more information on the installation, usage, and examples, visit: https://www.cdslab.org/paramonte
ParaMonte design goals
ParaMonte has been developed while bearing the following design goals in mind:
Full automation of all Monte Carlo simulations to the highest levels possible to ensure the highest level of user-friendliness of the library and minimal time investment requirements for building, running, and post-processing of simulation models.
Interoperability of the core library with as many programming languages as currently possible, including C, C++, Fortran, MATLAB, Python, with ongoing efforts to support other popular programming languages.
High-Performance meticulously-low-level implementation of the library to ensure the fastest-possible Monte Carlo simulations.
Parallelizability of all simulations via two-sided and one-sided MPI/Coarray communications while requiring zero-parallel-coding efforts by the user.
Zero-dependence on external libraries to ensure hassle-free ParaMonte library builds and ParaMonte simulation runs.
Fully-deterministic reproducibility and automatically-enabled restart functionality for all simulations up to 16 digits of precision as requested by the user.
Comprehensive-reporting and post-processing of each simulation and its results, as well as their automatic storage in external files to ensure the simulation results will be comprehensible and reproducible at any time in the distant future.
Installation
The pre-built ready-to-use libraries are available on the release page of the ParaMonte library on GitHub. Each prebuilt ParaMonte library automatically ships with a full-fledged set of example codes and build scripts.
Alternatively, you can build the library from the source in the GitHub repository of the project. The ParaMonte library installation/build process is fully automated for all of the supported programming languages. Currently, the following compiler suites are supported for builds from source:
Compiler Suite | Linux | macOS | Windows (64bit) |
---|---|---|---|
GNU Compiler Collection > 8.4 | ✓ | ✓ | ✗ |
Intel Parallel Studio > 19.0.4 | ✓ | ✓ | ✓ |
For more information and quick-start in the programming language of your choice, visit the ParaMonte library homepage.
Dependencies
Beyond an optional MPI runtime library for parallel simulations, the ParaMonte kernel has zero dependency on external third-party libraries or packages.
Parallelism
The ParaMonte library relies on the Message Passing Interface (MPI) standard for inter-processor communications. To run a parallel simulation, you will have to have a compatible MPI runtime library installed on your system. In most cases, ParaMonte will automatically install the required missing libraries on your system (with your permission). These automatic checks and installations happen when you download and install or use the library on your system, for the first time. If the automatic installation is unsuccessful, you can also install the libraries manually on your system:
For more information, visit https://www.cdslab.org/paramonte/.
Example usage instructions
For complete organized up-to-date instructions, visit: cdslab.org/pm
For a quick look into language-specific README.md instructions, visit:
Citing ParaMonte
The ParaMonte library is an honor-ware and its currency is acknowledgment and citations.
If you use ParaMonte, please acknowledge it by citing the ParaMonte library's main publications as listed in ACKNOWLEDGMENT.md.
Visit the ParaMonte library homepage to access the PDF version of these files free of charge.
License
What does this license mean?
Essentially, all we are asking from the users or developers is to
explicitly acknowledge the use of this library or any concepts or parts of it in their education, research, or software (free or commercial).
This is a free software, so help us keep it freely available to the public by redistributing the library and contributing to it. If you have questions or concerns about the license, do not hesitate to contact us (shahmoradi@utexas.edu).
Authors and contributors
For more information, visit cdslab.org/pm or contact Amir Shahmoradi: shahmoradi@utexas.edu
Author: cdslaborg
Source code: https://github.com/cdslaborg/paramonte
License: MIT license
1657989198
OTS
ots is an interface to libots - The Open Text Summarizer.
# ruby & ruby development libraries (not needed if you use rvm)
sudo apt-get install ruby1.9.1-dev ruby1.9.1
# libxml2 and glib development libraries
sudo apt-get install libxml2-dev libglib2.0-dev
# install ots
gem install ots
# update homebrew to latest & greatest version
GIT_SSL_NO_VERIFY=1 brew update
# optional: macosx normally has libxml2 installed if not try
brew install libxml2
# install glib
brew install glib
# setup the environment variables in order to install ots
export CPPFLAGS=-I/usr/local/Cellar/glib/2.30.2/include/glib-2.0/
export LDFLAGS=-L/usr/local/Cellar/glib/2.30.2/lib/
export PKG_CONFIG_PATH=/usr/local/Cellar/glib/2.30.2/lib/pkgconfig/
# install ots
gem install ots
OTS
.parse #=> OTS::Article
.languages #=> Array
OTS::Article
.new
#topics #=> Array
#keywords #=> Array
#summarize #=> Array
require 'ots'
article = OTS.parse("I think I need some ice cream to cool me off. It is too hot down under")
article = OTS.parse("j'ai besoin de la crème glacée. il fait trop chaud en australie.", language: "fr")
article = OTS.parse("j'ai besoin de la crème glacée. il fait trop chaud en australie.", dictionary: "custom.xml")
article.topics
article.keywords
article.summarize(percent: 50)
article.summarize(sentences: 1)
OTS.languages #=> list of supported language dictionaries baked-in to libots
https://github.com/ssoper/summarize
Author: Deepfryed
Source Code: https://github.com/deepfryed/ots
License: MIT