Friday, October 11, 2024

Do you want your python code to access C/C++ code? use SWIG...

 SWIG (Simplifies Wrapper and Interface Generator) is an interface compiler that connects programs written in C and C++ with scripting languages such as Perl, Python, Ruby, and Tcl. It works by taking the declarations found in C/C++ header files and using them to generate the wrapper code that scripting languages need to access the underlying C/C++ code.

Using SWIG, you can replace the main() function of a C/C++ program with a scripting interpreter from which you can control the application. This adds quite a lot of flexibility and makes the program "programmable." 

SWIG allows C/C++ programs to be placed in a scripting environment that can be used for testing and debugging. For example, you might test a library with a collection of scripts or use the scripting interpreter as an interactive debugger.

With SWIG, different C/C++ programs can be turned into scripting language extension modules. These modules can then be combined together to create new and interesting applications.

SWIG is sometimes compared to interface definition language (IDL) compilers such as those you find with systems such as CORBA and COM. Although there are a few similarities, the whole point of SWIG is to make it so you don't have to add an extra layer of IDL specifications to your application.

SWIG requires little, if any, modifications to existing code. For the most part, it encourages you to keep a clean separation between C/C++ and its scripting interface.

The primary audience of SWIG is C/C++ programmers who want to add a scripting language component to their applications.

So... here we go...

My experimentation with SWIG...

Step I. MyClass.h

#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass {
public:
    MyClass();
    ~MyClass();
    void set_value(int val);
    int get_value() const;

private:
    int value;
};

#endif

Step II

MyClass.cpp

#include "MyClass.h"

MyClass::MyClass() : value(0) {}

MyClass::~MyClass() {}

void MyClass::set_value(int val) {
    value = val;
}

int MyClass::get_value() const {
    return value;
}


Step III


MyClass.i - the SWIG interface file...


%module MyClass
%{
#include "MyClass.h"
%}

%include "MyClass.h"


Step IV


Generate the Wrapper Code Using SWIG


Run in terminal the following command


swig -python -c++ MyClass.i


This generates two files:

  • MyClass_wrap.cxx: The C++ wrapper code SWIG generates.
  • MyClass.py: The Python module that SWIG creates, which interfaces with the C++ code.

Step V

Then compile the C++ code and the SWIG-generated wrapper using g++ or another compiler. Make sure to link against Python libraries as shown below


g++ -fPIC -shared MyClass_wrap.cxx MyClass.cpp -I/usr/include/python3.x -o _MyClass.so


Here:

  • -fPIC ensures that the code is position-independent (required for shared libraries).
  • -shared tells the compiler to generate a shared library (_MyClass.so).
  • The -I flag specifies the path to Python headers.

Step VI

Once compiled, you can use the MyClass module in Python:

import MyClass

# Create an instance of MyClass
obj = MyClass.MyClass()

# Set and get value using the wrapped C++ methods
obj.set_value(100)
print(obj.get_value())  # Output: 100


Tuesday, September 24, 2024

And miles to go before I sleep - delving into the FreeCAD source code...

 There are many differences between learning a programming language and implementing it in a big real-life project. Hence as a guru of my young son, Ridit, I was looking for a real-life software source code to teach him the practicality of programming languages. I built the Blender source code, but Blender is a mix of various software languages, and many parts of it are written in C. As my son knows C++, Python and Java, i was on the look out for an open source project written purely in these languages.

And Voila... 

I got FreeCAD which is written in modern C++ (C++ 17 and 20) and Python.

So, today I cloned the FreeCAD source code from Github and can build it using QTCreator.

FreeCAD is an open-source parametric 3D modeler, and its source code is written in C++ and Python, making it a rich resource for learning programming concepts. Here are some benefits and considerations for using FreeCAD as a learning platform:

- Real-world application: 

Working with FreeCAD's code exposes learners to a large, professional-grade software project, helping them understand how C++ is applied in real-world engineering applications.

- Object-Oriented Programming: 

Since FreeCAD uses a lot of object-oriented principles, it provides a solid opportunity to understand OOP in-depth, including classes, inheritance, polymorphism, and design patterns.

- Boost Library:

FreeCAD uses the Boost C++ libraries, which are widely used in the C++ community. Learning Boost can significantly improve one's C++ skills.

- Multi-threading and Concurrency:

In advanced projects like FreeCAD, learners can explore more complex topics like multi-threading, resource management, and optimization.

- Cross-language interaction:

FreeCAD integrates Python as a scripting interface. This allows learners to see how different languages can work together, which is valuable in software development.

- Community support:

The FreeCAD community is active, and a young learner can interact with experienced developers, get feedback, and participate in discussions to enhance their skills.

As my son is getting ready for a future career in 3D Software Engineering, I am sure, this journey through the source code of FreeCAD will be a really great yet challenging experience.

So... here we go...

Our journey is about to start...



amader jatra hala shuru

আমাদের   যাত্রা হল শুরু   এখন,   ওগো কর্ণধার।

                   তোমারে         করি নমস্কার।

এখন        বাতাস ছুটুক, তুফান উঠুক, ফিরব না গো আর--

                   তোমারে         করি নমস্কার॥

আমরা   দিয়ে তোমার জয়ধ্বনি   বিপদ বাধা নাহি গণি

                                  ওগো কর্ণধার।

এখন    মাভৈঃ বলি ভাসাই তরী, দাও গো করি পার--

                   তোমারে    করি নমস্কার॥

এখন    রইল যাত্রা আপন ঘরে   চাব না পথ তাদের তরে

                                  ওগো কর্ণধার।

যখন    তোমার সময় এল কাছে তখন কে বা কার--

                   তোমারে         করি নমস্কার।

মোদেরকেবা আপন, কে বা অপর, কোথায় বাহির, কোথা বা ঘর

                                  ওগো কর্ণধার।

চেয়ে    তোমার মুখে   মনের সুখে   নেব সকল ভার--

                   তোমারে         করি নমস্কার ॥

আমরা  নিয়েছি দাঁড়, তুলেছি পাল,   তুমি এখন ধরো গো হাল

                                  ওগো কর্ণধার।

মোদের   মরণ বাঁচন ঢেউয়ের নাচন, ভাবনা কী বা তার--

                   তোমারে         করি নমস্কার।

আমরা  সহায় খুঁজে পরের দ্বারে   ফিরব না আর বারে বারে

                                  ওগো কর্ণধার।

কেবল  তুমিই আছ আমরা আছি     এই জেনেছি সার--

                   তোমারে         করি নমস্কার ॥

Saturday, September 21, 2024

Composite Pattern in Rust - my exploration continues...

In this ever evolving world of programming languages when each day a new language pops up, it's difficult to maintain sanity - that's why impostor syndrome is very common in the software industry. But whatever may be the case, there are some fundamental concepts which remain intact. For example, the event handler loops are almost for every event driven OS. Similarly, the design pattern concepts - it's truly language-agnostic.

Language syntax may change. But the basic principles of software design will remain the same - the same abstraction, encapsulation, inheritance, composition - all remain same.

That's why learning design pattern is such an important goal in the software industry.

Design patterns provide reusable solutions to common problems in software design. The language may differ (like using inheritance in object-oriented languages or using traits in Rust), but the patterns are language-agnostic in concept.

It enforces us to rise above the language and look into a piece of code from a designer's perspective.

So.... here we go...

My implementation of composite pattern in Rust.

use std::vec;
use std::any::type_name;

// Define a trait with a default method to print the type name
trait GetTypeName {
fn get_type_name(&self) -> &'static str {
type_name::<Self>()
}
}

// Implement the trait for any type
impl<T> GetTypeName for T {}

fn print_type_name(obj: &dyn GetTypeName) {
println!("The type name is: {}", obj.get_type_name());
}
trait Shape : ShapeClone{
fn new() -> Self where Self: Sized;
fn add(&mut self, shape : Box<dyn Shape>){
println!("Aloha... It's a leaf.... can't add more components to it...");//default behavior
}
fn remove(&mut self,shape : Box<dyn Shape>){
println!("Aloha... It's a leaf.... can't remove components from it...");//default behaviour
}
fn get_parent(&self) -> Option<Box<dyn Shape>>;
fn set_parent(&mut self, shape: Box<dyn Shape>);
fn display(&self);
}
trait ShapeClone {
fn clone_box(&self) -> Box<dyn Shape>;
}

impl<T> ShapeClone for T
where
T: 'static + Shape + Clone,
{
fn clone_box(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
}

impl Clone for Box<dyn Shape> {
fn clone(&self) -> Box<dyn Shape> {
self.clone_box()
}
}

#[derive(Clone)]
struct Point{
x:i32,
y:i32,
parent: Option<Box<dyn Shape>>,
}
#[derive(Clone)]
struct CompositeShape{
parent : Option<Box<dyn Shape>>,
list_of_shapes : Vec<Box<dyn Shape>>,
}

impl Shape for CompositeShape{
fn new() -> Self
where
Self: Sized
{
Self {
parent: None,
list_of_shapes: Vec::new(),
}
}

fn add(&mut self, shape: Box<dyn Shape>){
self.list_of_shapes.push(shape.clone());
}
fn remove(&mut self, shape: Box<dyn Shape>){
self.list_of_shapes.pop();
}
fn get_parent(&self) -> Option<Box<dyn Shape>>{
self.parent.clone()
}
fn set_parent(&mut self, shape: Box<dyn Shape>){
self.parent = Option::from(shape);
}
fn display(&self){
for shape in self.list_of_shapes.iter(){
shape.display();
}
}
}

impl Shape for Point{
fn new() -> Self
where
Self: Sized
{
Self { x:0, y:0, parent: None } // Can also write Point { x, y }
}

fn get_parent(&self) -> Option<Box<dyn Shape>>{
self.parent.clone()
}

fn set_parent(&mut self, shape: Box<dyn Shape>) {
self.parent = Option::from(shape);
}

fn display(&self) {
println!("X : {}, Y: {}", self.x, self.y);
}
}

fn main() {
let mut line1 : Box<dyn Shape> = Box ::new(CompositeShape::new());
let mut quadrilateral1 : Box<dyn Shape> = Box ::new(CompositeShape::new());
// Create points
let mut p1:Box<dyn Shape> = Box::new(Point { x: 1, y: 1, parent: None });
let mut p2:Box <dyn Shape> = Box::new(Point { x: 2, y: 2, parent: None });
let mut p3:Box<dyn Shape> = Box::new(Point { x: 10, y: 20, parent: None });
let mut p4:Box <dyn Shape> = Box::new(Point { x: 60, y: 90, parent: None });

line1.add(p1.clone());
line1.add(p2.clone());

quadrilateral1.add(p1.clone());
quadrilateral1.add(p2.clone());
quadrilateral1.add(p3.clone());
quadrilateral1.add(p4.clone());

//setting the parents of the two points
p1.set_parent(line1.clone());
p2.set_parent(line1.clone());

//Trying to add to a leaf
p1.add(p2.clone());

println!("The starting and ending points of the line1 are...");
line1.display();
println!("The four vertices of the quadrilateral are...");
quadrilateral1.display();
}
And here's my exploration of the Composite Design Pattern back in 2008 using C++.



And here we go... Composite Design Pattern in Python...


Enjoy...

Friday, September 20, 2024

The Bridge Pattern in Rust...

In modern software design, using composition (via the Bridge pattern) instead of inheritance is often considered a better approach, particularly when working with flexible, scalable systems. The Bridge pattern is a structural design pattern that decouples an abstraction from its implementation, allowing the two to vary independently. This pattern promotes composition by separating the interface from the implementation, which solves many problems associated with inheritance.

Here is the code of Bridge pattern implemented in Rust...

trait Color {
fn new(&self) {
}
fn get_name(&self) -> String;
}

struct Red;
struct Black;

impl Color for Red {
fn new(&self) {
println!("The color is Black");
}

fn get_name(&self) -> String {
"Red".to_string()
}
}

impl Color for Black {
fn new(&self) {
println!("The color is Black");
}

fn get_name(&self) -> String {
"Black".to_string()
}
}

trait Gear {
fn new(&self){
}

fn get_name(&self) -> String;
}

struct AutoGear;
struct ManualGear;

impl Gear for AutoGear {
fn new(&self){
println!("The gear is AutoGear");
}

fn get_name(&self) -> String {
"AutoGear".to_string()
}
}

impl Gear for ManualGear {
fn new(&self){
println!("The gear is Manual Gear");
}

fn get_name(&self) -> String {
"ManualGear".to_string()
}
}

trait Vehicle {

fn set_color(&mut self, color : Box<dyn Color>) {}
fn set_gear (&mut self, gear : Box<dyn Gear>) {}

fn display_attributes(&self) { }


}

#[derive()]
struct SmallCar{
color: Box<dyn Color>,
gear: Box<dyn Gear>,
}
#[derive()]
struct Truck{
color: Box<dyn Color>,
gear: Box<dyn Gear>,
}

impl Vehicle for SmallCar {
fn set_color(&mut self, color : Box<dyn Color>) {
self.color = color;
}
fn set_gear(&mut self, gear : Box<dyn Gear>) {
self.gear = gear;
}

fn display_attributes(&self) {
println!("The vehicle color is {:?}", self.color.get_name());
println!("The vehicle gear is {:?}", self.gear.get_name());
}
}

impl Vehicle for Truck {
fn set_color(&mut self, color : Box<dyn Color>) {
self.color = color;
}
fn set_gear(&mut self, gear : Box<dyn Gear>) {
self.gear = gear;
}

fn display_attributes(&self) {
println!("The vehicle color is {:?}", self.color.get_name());
println!("The vehicle gear is {:?}", self.gear.get_name());
}
}

fn main() {
let color = Box::new(Red);
let gear = Box::new(AutoGear);
let truck = Truck {
color: color, gear:gear,
};
truck.display_attributes();
}

Let me tell you in detail what is there in this example.

Here we have a top-level root class called Vehicle having two attributes - color and gear.

The color may be Red and White whereas the Gear may be Manual and Auto.

Now if we put all of these in a monolithic class hierarchy, as shown in the left diagram - there will be many classes.

So, to do it in a better fashion, we maintain two different inheritance hierarchies namely one for Color and another for Gear. And the Vehicle hierarchy is maintained separately.

So from the vehicle hierarchy, we pick up any color and any type of Gear we want from the Color and Gear inheritance hierarchies respectively as shown in the right-side diagram.

The result is that there will be few classes to maintain.

This is exactly what is explained in the following section.

Look at the UML diagram on the left - that is the class hierarchy without using Bridge Pattern. Look at the number of classes - it's many classes.

Now look at the class diagram at the right- look at how fewer classes can manage the same level of different classes if we use the Bridge Pattern




Using composition with the Bridge pattern is often a superior design choice compared to inheritance. It:

- Avoids the pitfalls of deep class hierarchies.
- Promotes code reuse and flexibility.
- Supports better maintainability and scalability.

By favoring composition over inheritance, we can create more modular, flexible, and maintainable systems, which align with modern software design principles such as SOLID.

Here's my implementation of the Bridge pattern in other languages - C++ and Python...

Thursday, September 19, 2024

My exploration of Rust continues... Mediator Design Pattern in Rust...

 This design pattern lets you reduce chaotic dependencies between objects. The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.

The Mediator interface declares a method used by components to notify the mediator about various events. The Mediator may react to these events and triggers specific components to execute different yet specific tasks.

The Base Component provides the basic functionality of storing a mediator's reference inside the component.

Concrete Components implement various functionality. They don't depend on other components.

Let me explain it to you with an example.

Suppose two students Ridit and Ishan take a lot of responsibility in a class. But something bad happens between them, and hence they don't talk to each other. So, here comes the ClassMonitor - as a Mediator between Ishan and Ridit - if Ridit does anything that needs Ishan to do another task, Ridit notifies the Class Monitor, and then the Class Monitor asks Ishan to execute the necessary task.


There are many uses for this design pattern. This design pattern can be found in most of the widget message-passing systems - individual widgets don't pass or communicate with each other - but they communicate through the container window.

For Android engineers - you remember how two fragments talk to each other through the container window.

Enjoy.

Happy learning.

Here's the source code for Mediator Pattern implemented through Rust.

use std::cell::RefCell;
use std::rc::Rc;

trait BaseStudent {
fn do_a(&self);
fn do_b(&self);
fn do_c(&self);
fn do_d(&self);
fn set_class_monitor(&mut self, monitor: Rc<RefCell<dyn ClassMonitar>>);
}

struct Ridit {
monitor: Option<Rc<RefCell<dyn ClassMonitar>>>,
}

struct Ishan {
monitor: Option<Rc<RefCell<dyn ClassMonitar>>>,
}

impl BaseStudent for Ridit {
fn do_a(&self) {
println!("Ridit does task A");
if let Some(ref monitor) = self.monitor {
monitor.borrow().notify("A".to_string());
}
}

fn do_b(&self) {
println!("Ridit does task B");
}

fn do_c(&self) {
println!("Ridit does task C");
}

fn do_d(&self) {
println!("Ridit does task D");
}

fn set_class_monitor(&mut self, monitor: Rc<RefCell<dyn ClassMonitar>>) {
self.monitor = Some(monitor);
}
}

impl BaseStudent for Ishan {
fn do_a(&self) {
println!("Ishan does task A");
}

fn do_b(&self) {
println!("Ishan does task B");
if let Some(ref monitor) = self.monitor {
monitor.borrow().notify("B".to_string());
}
}

fn do_c(&self) {
println!("Ishan does task C");
}

fn do_d(&self) {
println!("Ishan does task D");
}

fn set_class_monitor(&mut self, monitor: Rc<RefCell<dyn ClassMonitar>>) {
self.monitor = Some(monitor);
}
}

trait ClassMonitar {
fn notify(&self, event: String);
}

#[derive(Clone)]
struct ConcreteClassMonitor {
ridit: Option<Rc<RefCell<dyn BaseStudent>>>,
ishan: Option<Rc<RefCell<dyn BaseStudent>>>,
}

impl ClassMonitar for ConcreteClassMonitor {
fn notify(&self, event: String) {
if event == "A" {
println!("ClassMonitor reacting to event A and asking Ishan to do task C");
if let Some(ref ishan) = self.ishan {
ishan.borrow().do_c();
}
}

if event == "B" {
println!("ClassMonitor reacting to event B and asking Ridit to do task D");
if let Some(ref ridit) = self.ridit {
ridit.borrow().do_d();
}
}
}
}

fn main() {
// Create instances of students as trait objects
let ridit: Rc<RefCell<dyn BaseStudent>> = Rc::new(RefCell::new(Ridit { monitor: None }));
let ishan: Rc<RefCell<dyn BaseStudent>> = Rc::new(RefCell::new(Ishan { monitor: None }));

// Create ConcreteClassMonitor as trait object (ClassMonitar)
let class_monitor: Rc<RefCell<dyn ClassMonitar>> = Rc::new(RefCell::new(ConcreteClassMonitor {
ridit: Some(Rc::clone(&ridit)),
ishan: Some(Rc::clone(&ishan)),
}));

// Set the monitor in the students
ridit.borrow_mut().set_class_monitor(Rc::clone(&class_monitor));
ishan.borrow_mut().set_class_monitor(Rc::clone(&class_monitor));

// Test the functionality
ridit.borrow().do_a(); // This will notify the monitor and trigger Ishan to do task C
ishan.borrow().do_b(); // This will notify the monitor and trigger Ridit to do task D
}

Monday, September 16, 2024

My tryst with Rust - through the subject of Design Pattern - implementation of Chain of Responsibility...

 I remember in my earlier phase as a software engineer, how I mapped the MFC's command routing algorithm to Chain of Responsibility - and when finally it became clear, there was immense joy for me.

I always say to my students that we should approach a problem not only from how's point of view but also from why's point of views.

Curiosity is one of the greatest traits for a software engineer - nurture that, grow that - if you want to extract joy from your day-to-day journey as a software engineer.

So here we go.

My today's contribution to the learning community - Chain of Responsibility design pattern using Rust.

The Chain of Responsibility design pattern is a behavioural design pattern that allows a request to pass through a series of handlers. Each handler can either handle the request or pass it to the next handler in the chain. This design pattern promotes loose coupling between the sender and receiver of a request, allowing more flexibility in handling specific actions.

Key Features of the Chain of Responsibility Pattern:

Decoupling: 

The sender of the request doesn't need to know which handler will process the request.

Dynamic Chains: 

You can change the chain of handlers at runtime or configure it based on the application's needs.

Multiple Handlers: 

A request can be processed by a series of handlers in sequence until one of them handles the request, or it can propagate through all of them.

Here's the source code...

#[derive(Clone)]
struct Request{
request_type : String,
}
impl Request{
fn new(request_type : String) -> Self{
Request{
request_type : request_type,
}
}
}

trait Employee {
fn set_successor(&mut self, successor:Box<dyn Employee>);
fn handle_request(&mut self, request: Request) ;
}
struct ProjectManager {
successor: Option<Box<dyn Employee>>,
}

struct TeamLeader {
successor: Option<Box<dyn Employee>>,
}

struct GeneralManager{
successor: Option<Box<dyn Employee>>,
}

struct CTO {
successor: Option<Box<dyn Employee>>,
}

impl Employee for CTO{

fn set_successor(&mut self, successor: Box<dyn Employee>) {
//end of the chain... no successor
}
fn handle_request(&mut self, request : Request) {
println!("I am the CTO... I must handle the request as this is the end of the chain");
println!("The request is handled at the CTO level...");
}
}

impl Employee for GeneralManager {
fn set_successor(&mut self, successor: Box<dyn Employee>) {
self.successor = Some(successor);
}

fn handle_request(&mut self, request : Request) {
if request.request_type == "generalmanager_level" {
println!("Handling the request at the General Manager level");
}
else if let Some(ref mut successor) = self.successor {
println!("I am the general manager...Forwarding the request to CTO...");
successor.handle_request(request);
}
}
}

impl Employee for ProjectManager {
fn set_successor(&mut self, successor: Box<dyn Employee>) {
self.successor = Some(successor);
}

fn handle_request(&mut self, request: Request) {
if request.request_type == "projectmanager_level" {
println!("Handling the request at the Project Manager level");
} else if let Some(ref mut successor) = self.successor {
println!("I am the Project Manager...Forwarding the request to General Manager");
successor.handle_request(request);
}
}
}

impl Employee for TeamLeader {
fn set_successor(&mut self, successor: Box<dyn Employee>) {
self.successor = Some(successor);
}

fn handle_request(&mut self, request : Request) {
if request.request_type == "teamleader_level" {
println!("Handling the request at the team_leader level");
}
else if let Some(ref mut successor) = self.successor {
println!("I am the teamleader....Forwarding the request to Project Manager");
successor.handle_request(request);
}
}
}

fn main() {
let request1 = Request::new("teamleader_level".to_string());
let request2 = Request::new("generalmanager_level".to_string());
let request3 = Request::new("cto_level".to_string());
let mut cto = CTO{successor: None};
let mut gm = GeneralManager{successor: None};
let mut manager = ProjectManager {successor: None};
let mut teamLeader = TeamLeader {successor: None};
gm.set_successor(Box::new(cto));
manager.set_successor(Box::new(gm));
teamLeader.set_successor(Box::new(manager));
teamLeader.handle_request(request3);
}

Enjoy...