C

C

C is a general-purpose programming language used for system programming, libraries, games and cross-platform.
Dang  Tu

Dang Tu

1660575900

Hướng Dẫn Hoàn Chỉnh Về Nạp Chồng Khối Lệnh Trong C ++

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 .

Nạp chồng hàm tạo trong C ++

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:

  1. Các hàm tạo mặc định - Một hàm tạo không có đối số là một hàm tạo mặc định.
  2. Các hàm tạo được tham số hóa - Một hàm tạo có các tham số được gọi là hàm tạo được tham số hóa.
  3. Copy Constructor - Một hàm tạo sao chép là hàm thành viên khởi tạo một đối tượng bằng cách sử dụng một đối tượng khác của cùng một lớp. 

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:

  1. Về cơ bản, các trình xây dựng cần phải có cùng tên với lớp.
  2. Thứ hai, các hàm tạo không có bất kỳ kiểu trả về nào.
  3. Cuối cùng, các hàm tạo luôn được khai báo là công khai.
  4. Trong khi tạo đối tượng phải được truyền theo yêu cầu để trình biên dịch biết phương thức khởi tạo nào cần gọi.

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.

Ứng dụng của các hàm tạo

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.

Khai báo nạp chồng phương thức khởi tạo

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ụ về nạp chồng phương thức khởi tạo

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.

Nạp chồng khối lệnh trong C ++

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.

Áp dụng quá tải các hàm tạo

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 

Hướng Dẫn Hoàn Chỉnh Về Nạp Chồng Khối Lệnh Trong C ++
Thierry  Perret

Thierry Perret

1660561380

Le Guide Complet De La Surcharge Des Constructeurs En C++

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 .

Surcharge de constructeur en C++

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 :

  1. Constructeurs par défaut – Un constructeur sans argument est un constructeur par défaut.
  2. Constructeurs paramétrés - Un constructeur qui a des paramètres est appelé constructeur paramétré.
  3. Constructeur de copie - Un constructeur de copie est la fonction membre qui initialise un objet à l'aide d'un autre objet de la même classe. 

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 :

  1. Les constructeurs doivent essentiellement avoir le même nom que la classe.
  2. Deuxièmement, les constructeurs n'ont pas de type de retour.
  3. Enfin, les constructeurs sont toujours déclarés publics.
  4. Lors de la création de l'objet, l'argument doit être passé en fonction de l'exigence de faire savoir au compilateur quel constructeur appeler.

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.

Application des constructeurs

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.

Déclaration de surcharge constructeur

Consultez la syntaxe de code suivante.

class A
{
   A()
   {
     body;   //constructor with no parameter 
   }

   A(int a, int b)
   {
     body;    //constructor with 2 parameters
   }
};

Exemples de surcharge de constructeur

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.

Surcharge de constructeur en C++

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.

Application de la surcharge des constructeurs

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 

Le Guide Complet De La Surcharge Des Constructeurs En C++

Полное руководство по перегрузке конструктора в C++

Прежде чем понять перегрузку конструктора, нам сначала нужно понять, что такое конструкторы. Конструкторы — это уникальные методы, вызываемые автоматически при создании объекта класса. Основная цель конструкторов — инициализировать элементы данных нового объекта .

Перегрузка конструктора в C++

При перегрузке конструктора C++ у нас может быть более одного конструктора в классе с одним и тем же именем, если каждый из них имеет другой список аргументов. Это очень похоже на перегрузку функций .

Существует три типа конструкторов:

  1. Конструкторы по умолчанию — конструктор без аргументов является конструктором по умолчанию.
  2. Параметризованные конструкторы . Конструктор с параметрами называется параметризованным конструктором.
  3. Конструктор копирования. Конструктор копирования — это функция-член, которая инициализирует объект, используя другой объект того же класса. 

Теперь, переходя к перегрузке конструктора , у нас есть более одного конструктора в классе, но они отличаются количеством присутствующих аргументов. 

Свойства конструкторов, которые следует учитывать при перегрузке конструктора:

  1. Конструкторы по существу должны иметь то же имя, что и класс.
  2. Во-вторых, у конструкторов нет возвращаемого типа.
  3. Наконец, конструкторы всегда объявляются как общедоступные.
  4. При создании объекта аргумент должен быть передан в соответствии с требованием, чтобы компилятор знал, какой конструктор вызывать.

Когда мы добавляем в класс более одного конструктора, мы называем его несколькими конструкторами.

Перегрузка конструктора очень похожа на перегрузку функций .

Конструктор перегружает изменение количества аргументов в текущем списке параметров конструктора. Следовательно, мы можем использовать конструкторы одного класса для разных целей.

Применение конструкторов

Предположим, нам нужно сгенерировать пакет для определенного набора учащихся, будь то 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);
}

См. следующий вывод.

Перегрузка конструктора в C++

Пример 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 

Полное руководство по перегрузке конструктора в C++
田辺  亮介

田辺 亮介

1660546786

C++ 中構造函數重載的完整指南

在了解構造函數重載之前,我們首先需要了解構造函數是什麼。構造函數是我們創建類對象時自動調用的唯一方法。構造函數的主要目的是初始化新對象的數據成員。

C++中的構造函數重載

在 C++ 構造函數重載中,我們可以在類中擁有多個同名的構造函數,只要每個構造函數具有不同的參數列表即可。它與函數重載非常相似。

構造函數分為三種:

  1. 默認構造函數——沒有參數的構造函數是默認構造函數。
  2. 參數化構造函數——具有參數的構造函數稱為參數化構造函數。
  3. 複製構造函數——複製構造函數是使用同一類的另一個對像初始化對象的成員函數。 

現在來到構造函數重載,我們在類中存在多個構造函數,但它們的不同在於存在的參數數量。 

重載構造函數時要記住的構造函數屬性:

  1. 構造函數本質上需要與類具有相同的名稱。
  2. 其次,構造函數沒有任何返回類型。
  3. 最後,構造函數總是被聲明為公共的。
  4. 在創建對象時,必鬚根據要求傳遞參數,讓編譯器知道要調用哪個構造函數。

當我們向一個類添加多個構造函數時,我們稱其為多個構造函數。

構造函數重載與函數重載非常相似。

構造函數重載改變構造函數當前參數列表中的參數數量。因此,我們可以將同一類的構造函數用於不同的目的。

構造函數的應用

假設我們必須為一組特定的學生生成一個批次,一個批次中有 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);
}

請參閱以下輸出。

C++中的構造函數重載

示例 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

C++ 中構造函數重載的完整指南
Python  Library

Python Library

1660304640

MicroPython: An Implementation Of Python 3.x on Microcontroller

The MicroPython project

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:

  • py/ -- the core Python implementation, including compiler, runtime, and core library.
  • mpy-cross/ -- the MicroPython cross-compiler which is used to turn scripts into precompiled bytecode.
  • ports/unix/ -- a version of MicroPython that runs on Unix.
  • ports/stm32/ -- a version of MicroPython that runs on the PyBoard and similar STM32 boards (using ST's Cube HAL drivers).
  • ports/minimal/ -- a minimal MicroPython port. Start with this if you want to port MicroPython to another microcontroller.
  • tests/ -- test framework and test scripts.
  • docs/ -- user documentation in Sphinx reStructuredText format. Rendered HTML documentation is available at http://docs.micropython.org.

Additional components:

  • ports/bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used mostly to control code size.
  • ports/teensy/ -- a version of MicroPython that runs on the Teensy 3.1 (preliminary but functional).
  • ports/pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers.
  • ports/cc3200/ -- a version of MicroPython that runs on the CC3200 from TI.
  • ports/esp8266/ -- a version of MicroPython that runs on Espressif's ESP8266 SoC.
  • ports/esp32/ -- a version of MicroPython that runs on Espressif's ESP32 SoC.
  • ports/nrf/ -- a version of MicroPython that runs on Nordic's nRF51 and nRF52 MCUs.
  • extmod/ -- additional (non-core) modules implemented in C.
  • tools/ -- various tools, including the pyboard.py module.
  • examples/ -- a few example Python scripts.

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).

The MicroPython cross-compiler, mpy-cross

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 version

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.

External dependencies

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 version

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.

Contributing

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.

Download details:

Author: micropython
Source code: https://github.com/micropython/micropython
License: View license

#python #c

MicroPython: An Implementation Of Python 3.x on Microcontroller
Best of Crypto

Best of Crypto

1660297920

Building Ledger Nano X Hardware Wallet Client for Fantom Account

Fantom Ledger App

Fantom Ledger Nano S and/or Ledger Nano X hardware wallet and secure key storage application.

Building the source

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.

Load the Application

make load

Download details:

Author: Fantom-foundation
Source code: https://github.com/Fantom-foundation/fantom-ledger
License: MIT license

#fantom #blockchain #c #python

Building Ledger Nano X Hardware Wallet Client for Fantom Account
Thierry  Perret

Thierry Perret

1659784168

Afficher Le Contenu Dynamique De GDB Dans Une Fenêtre Personnalisée

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.

Chargement des valeurs d'historique

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_indexvariable 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_indexvariable représentera le prochain index que vous devez extraire de l'historique des valeurs de GDB.

Ensuite, ajoutez deux nouvelles méthodes à la history_windowclasse, 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_valuemé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 _linesliste. 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.subappel, 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.pyfichier :

import re

La _updateméthode appelle juste _add_next_history_valuejusqu'à ce que toutes les valeurs d'historique aient été traitées.

Enfin, vous devez appeler _updateà deux endroits.

Tout d'abord, appelez _updatedepuis 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 _linesliste. 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 à _updatepartir de la _before_promptméthode, en remplaçant la ligne de débogage existante. La _before_promptmé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 :

L'écran Historique des valeurs affiche dynamiquement les valeurs dans GDB.

Figure 1 : L'écran Historique des valeurs affiche dynamiquement les valeurs dans GDB.

Préparation au défilement

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_windowclasse :

    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_countméthode renvoie le nombre d'éléments d'historique qui ont été chargés dans la _linesvariable.

La _display_startmé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_startrenvoie 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 rendermé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 heightnombre de lignes à partir de _display_start(). Le - 1est obligatoire car _display_start()renvoie un index d'historique, qui compte à partir de 1, alors qu'il _liness'agit d'une liste Python, indexée à partir de 0.

Après ces changements, le history_windowdevrait fonctionner comme avant, et vous êtes maintenant prêt pour la dernière partie de ce didacticiel.

Prise en charge du défilement

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_startmé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_starta été défini, la fenêtre le traite comme l'index pour démarrer l'affichage. Si _vscroll_startn'est pas défini, la méthode fait les choses exactement comme avant.

Enfin, ajoutez la vcsrollméthode suivante à votre history_windowclasse :

    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' numargument 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 vscrollmé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_startsur 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

Afficher Le Contenu Dynamique De GDB Dans Une Fenêtre Personnalisée

Как отображать динамический контент из GDB в пользовательском окне

Это вторая статья из серии из двух частей, посвященной отображению информации из отладчика 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 показано, как должно выглядеть окно в действии после ввода нескольких команд в командном окне:

Экран Value History динамически отображает значения в GDB.

Рисунок 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

Как отображать динамический контент из GDB в пользовательском окне
Minh  Nguyet

Minh Nguyet

1659768248

Cách Hiển Thị Nội Dung động Từ GDB Trong Cửa Sổ Tùy Chỉnh

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.

Đang tải các giá trị lịch sử

Để 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_indexsẽ đượ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_indexbiế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_windowlớ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_valuethứ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 _linesdanh 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.subgọ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.pytệp:

import re

Phương _updatethức chỉ gọi _add_next_history_valuecho đế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 _updatetừ __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 _linesdanh 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 _updatetừ _before_promptphương thức, thay thế dòng gỡ lỗi hiện có. Phương thức đầy đủ _before_promptbâ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:

Màn hình Lịch sử giá trị hiển thị động các giá trị trong GDB.

Hình 1: Màn hình Lịch sử giá trị hiển thị động các giá trị trong GDB.

Chuẩn bị cuộn

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_windowlớ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_countthức trả về số lượng mục lịch sử đã được tải vào _linesbiến.

Phương _display_startthứ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_starttrả 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 renderphươ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 heightsố dòng bắt đầu từ _display_start(). Là - 1bắt buộc vì _display_start()trả về chỉ mục lịch sử, được tính từ 1, trong khi _lineslà danh sách Python, được lập chỉ mục từ 0.

Sau những thay đổi này, công history_windowcụ 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.

Hỗ trợ cuộn

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_startphươ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_startkhô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 vcsrollphương thức sau vào history_windowlớ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 numsố 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 vscrollphá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_startthà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

Cách Hiển Thị Nội Dung động Từ GDB Trong Cửa Sổ Tùy Chỉnh
山田  千代

山田 千代

1659760882

如何在自定義窗口中顯示來自 GDB 的動態內容

這是關於在調試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()

接下來,添加對_updatefrom_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 顯示了在命令窗口中輸入一些命令後窗口的實際效果:

Value History 屏幕動態顯示 GDB 中的值。

圖 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_startNone。這表明當新的歷史值出現時,它們應該被添加到窗口的底部,將舊值從頂部推開。

這樣,您的窗口就完成了。您可以向後滾動以查看所有舊的歷史記錄值,然後再次向前滾動以查看最新的歷史記錄值。

鏈接:https ://developers.redhat.com/articles/2022/08/04/display-dynamic-content-gdb-custom-window#

#gdb #python #c

如何在自定義窗口中顯示來自 GDB 的動態內容
Monty  Boehm

Monty Boehm

1659499020

CL Lib to Parse C Headers, and Generate FFI for CL(CFFI) & Julia

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..)

Considerations

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 #defines 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 #defines are values or not.

(Common Lisp side)Dependencies

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.

TODO(maybe)

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?

Copyright

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

#julia #c 

CL Lib to Parse C Headers, and Generate FFI for CL(CFFI) & Julia
Monty  Boehm

Monty Boehm

1659491460

Julia-ffi: C Header Parser, AutoFFIing and FFI Libraries From It

Julia ffi and C parser for generating it, and some various utilities.

This project contains:

  • In development is a tool to autoFFI C libraries. The current FFIs are made with a Common Lisp parser, but when ready, the Julia parser will be used instead.
  • FFI-ed C libraries, with extras to utilize Julia's features.

This project also contains a utility lib. Some of which may be better off from a standard lib/more standard way to do it.

Outputs of autoffi-er provided

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.

'Install'

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..

Stuff reasonably usable:

Opengl

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.

SDL

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.

The rest.

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

  • Get the parser to autoFFI.
  • Will want a standard way to deal with:
  • analogous to C.
  • automatically created extra stuff.
  • manually created extra.

Author: o-jasper
Source Code: https://github.com/o-jasper/julia-ffi 
License: MIT license

#julia #c 

Julia-ffi: C Header Parser, AutoFFIing and FFI Libraries From It
Rubalema  Sonia

Rubalema Sonia

1658944140

A Curated List of Game Network Programming Resources

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

Articles

Talks

Libraries

  • C / C++
    • ENet - Simple and robust reliable UDP networking library.
    • GameNetworkingSockets - Valve's internal (Steam) network transport layer for games.
    • GGPO - Good Game, Peace Out Rollback Network SDK.
    • KCP - A fast and reliable ARQ protocol.
    • RakNet - Full-featured and mature reliable UDP networking engine.
    • TNL2 - (Inactive) Torque Networking Library 2 which is quite similar to TRIBES Networking Model.
    • yojimbo - Reliable UDP networking library for client/server games with dedicated servers.
  • C#
    • Barebones Master Server - Backend framework with auth, profile, lobby, chat features for Unity.
    • DarkRift 2 - Unity focused high-performance multi-threaded multiplayer networking solution.
    • FishNet - Unity networking solution aimed towards reliability, ease of use, efficiency, and flexibility.
    • Forge Networking - Unity focused real-time multiplayer networking solution.
    • Lidgren.Network - Reliable UDP networking library (.NET/Mono/Unity).
    • LiteNetLib - Lite reliable UDP networking library (.NET/Mono/Unity).
    • MagicOnion - Unified Realtime/API framework for .NET platform and Unity.
    • Mirror - A community replacement for Unity's abandoned UNET Networking System.
    • Netcode for GameObjects - Unity's official high-level netcode SDK for GameObject workflows.
    • NetStack - Lightweight toolset for creating concurrent networking systems for multiplayer games.
    • Networker - TCP and UDP networking library (.NET/Unity).
    • Normcore - Seamless multiplayer game networking for Unity (Cloud/SaaS).
    • Photon Engine - Hybrid multiplayer game networking platform (Cloud/SaaS).
    • RiptideNetworking - Lightweight C# networking solution for multiplayer games.
    • SocketWeaver - Multiplayer cloud services designed for the Unity engine (Cloud/SaaS).
  • Go
    • Nakama - Open-source backend infrastructure for multiplayer games (also with Unity/C# SDK).
    • GoWorld - Scalable Distributed Game Server Engine with Hot Swapping (and Unity demo!).
  • Java
    • SmartFoxServer - Massive multiplayer game server with advanced built-in features.
  • JavaScript
    • Actionhero - A node.js API server framework for TCP sockets, websockets and HTTP clients.
    • Colyseus - Authoritative multiplayer game server backend framework.
    • Kalm - Socket manager/optimizer library with custom congestion control for Node.js and browsers.
    • SocketCluster - Scalable multi-process HTTP & real-time server framework.

Tools

  • CapAnalysis - Web visual tool to analyze captured network traffic. (Ubuntu, Debian)
  • clumsy - Network condition simulation utility. (Windows)
  • netem - Network emulation for testing protocols. (Linux)
  • mitmproxy - Web debugging proxy server. (Windows, macOS, Linux)
  • Network Link Conditioner - Network environment simulation utility. (macOS, iOS)
  • Network Protocol Analyzer - Tool for analysing, debugging and monitoring connections. (Windows)
  • Network Simulator (ns) - Network simulator targeting research and educational use. (macOS, Linux)
  • Postman - Web API debugging and development client. (Windows, macOS, Linux)
  • websocat - CLI client for WebSockets like netcat or curl. (Windows, macOS, Linux)
  • Wireshark - Network traffic analyzer tool. (Windows, macOS, Linux)

Download details:
Author: ThusWroteNomad
Source code: https://github.com/ThusWroteNomad/GameNetworkingResources
License:

#unity #gamedev  #c

A Curated List of Game Network Programming Resources
Archie  Powell

Archie Powell

1658210400

ParaMonte ML: Plain Powerful Parallel Monte Carlo and MCMC Library

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 SuiteLinuxmacOSWindows (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:

  • On Windows and Linux operating systems, we highly recommend downloading and installing the Intel MPI runtime libraries, which is available to the public free of charge.
  • On macOS, we recommend Open-MPI since the Intel MPI library does not support macOS.

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

MIT 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

Amir Shahmoradi

  • astrophysicist/bioinformatician by training (and a science-lover in general),
  • Ph.D. in computational physics/bioinformatics from the University of Texas at Austin,
  • currently a faculty member of Physics and Data Science at The University of Texas at Arlington,
  • with teaching/research experience/background in computational and data sciences, statistics, data analysis, and modeling, stochastic processes, Monte Carlo Methods, Bayesian probability theory, high energy physics, astronomy and astrophysics, computational physics, Molecular Dynamics simulations, biomedical science and MRI data analysis, bioinformatics and evolutionary biology (viral evolution, protein dynamics, and interactions),
  • contact: shahmoradi@utexas.edu

Fatemeh Bagheri

  • physicist / cosmologist by training,
  • currently a UTA Physics member,
  • deep philosophical thinker,
  • contact: Fatemeh.Bagheri@uta.edu

Shashank Kumbhare

Joshua Osborne

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

#machine-learning #python #cpluplus #c 

ParaMonte ML: Plain Powerful Parallel Monte Carlo and MCMC Library
Royce  Reinger

Royce Reinger

1657989198

Ots: Ruby Bindings to Open Text Summarizer

OTS

ots is an interface to libots - The Open Text Summarizer.

Dependencies

  • ruby 1.9.1 or later
  • libxml2
  • glib2.0
  • homebrew (on MacOSX)

Installation

Debian flavors of Linux


  # 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

MacOSX


 # 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

API

  OTS
    .parse        #=> OTS::Article
    .languages    #=> Array

  OTS::Article
    .new
    #topics       #=> Array
    #keywords     #=> Array
    #summarize    #=> Array

Usage

  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

See Also

https://github.com/ssoper/summarize

Author: Deepfryed
Source Code: https://github.com/deepfryed/ots 
License: MIT

#ruby #text #c 

Ots: Ruby Bindings to Open Text Summarizer