Sunday, August 17, 2025

What Could Have Been: The Saga of Semiconductor Limited (SCL)...An untold chapter in India's technology dreams...

In the heart of Mohali, far from the global buzz of Silicon Valley, stood a dream.

A dream wrapped in silicon wafers, precision instruments, and the quiet hum of clean rooms — Semiconductor Limited (SCL). It was India's early moonshot into semiconductor self-reliance. Long before "Make in India" and PLI schemes became the rallying cry, SCL was born with a vision to place India on the global semiconductor map.

But this is a story of what could have been.

馃И The Spark of a Revolution

Founded in the late 1970s and operational by early 1980s, SCL was tasked with designing and fabricating integrated circuits — the very foundation of modern electronics. Unlike most public sector units, SCL wasn’t building dams, laying tracks, or manufacturing steel.

It was building brains — the digital brains of modern machines.

At a time when countries like South Korea and Taiwan were just beginning to formulate their semiconductor strategy, India already had a working fab. Engineers trained abroad came home. Chip design, VLSI, and fabrication—terms alien to most Indians then—were common language within the SCL campus.

There was hope. There was talent. There was purpose.

馃敟 The Tragedy: A Fire in the Cleanroom

Then came February 1989 — a date etched in the memory of Indian technologists.

A mysterious fire broke out inside the Class 100 clean room of SCL.

A place that must be cleaner than an operating theatre — where even a speck of dust can ruin a chip — was suddenly engulfed in flames. Equipment worth crores, research worth years, and hope worth a generation was reduced to ashes.

Till date, no conclusive public report explains what happened.

Some said it was an accident. Some whispered sabotage. Others claimed it was negligence.

The timing was eerie. India was just beginning to open up. Global semiconductor giants were eyeing cheap labor and new markets. Was SCL’s rise a threat to someone?

The conspiracy theories remain — but the fire was real.

馃З The Aftermath: From Dream to Dormancy

After the fire, the project was nationalized under ISRO.

SCL was revived, but its ambition was clipped. It was reoriented to focus on strategic defense and space electronics, making rad-hard chips for satellites and missiles — no longer for the mass market. The dream of a consumer-grade semiconductor ecosystem faded.

Meanwhile, in those same decades:

  • Taiwan built TSMC
  • South Korea backed Samsung
  • China built SMIC
  • India? Had SCL.

馃尡 Seeds Never Watered

What if the fire never happened?

What if SCL had received consistent funding and global partnerships?

Would India today be a chip superpower, exporting logic and memory chips, leading 5G infrastructure, or even building advanced GPUs?

The talent was there. The vision was there. But perhaps, the political will wasn't.

We still build great software. We still run backend for the world. But the chip that powers it? It's made elsewhere.

馃洜 The Present Echoes

Today, in 2025, the government is trying again — with PLI schemes, DLI initiatives, and a push for fabs in Gujarat and Karnataka. Global players like Micron, Foxconn, and AMD are talking about investing in India.

But buried beneath the headlines is the ghost of SCL, whispering:

“We tried. You ignored.”

馃實 Final Thoughts: History as a Lesson

India's semiconductor saga did not start in 2022.
It began with SCL in the 1980s.

We were not late to the race.
We were there at the starting line.
We just stopped running.

Today, as India dreams of semiconductor glory once again, may we remember SCL — not as a failure, but as a pioneer that laid the first stone, suffered in silence, and warned us of what happens when we forget to protect our dreams.

Because dreams, like wafers, are delicate.
They burn easily.
But their ashes still carry charge.

Thursday, August 14, 2025

The d茅j脿 vu - more than 30 years after engineering college - multiplying a vector by exp(j胃) in the complex plane is nothing but rotating it by an angle 胃...

It was 1989, a humid afternoon in the engineering college classroom. The blackboard was already half-white from chalk dust, and our mathematics professor — a bespectacled man who loved quoting Euler more than Bollywood — scribbled furiously:

ej=cos+jsine^{j\theta} = \cos\theta + j \sin\theta

"This, my dear students," he declared, "is the key to rotating any vector in the plane. Multiply your vector by eje^{j\theta} and watch it turn by \theta degrees without changing its length."

At 17 years old, I copied the formula into my notebook without much ceremony. My mind was more occupied with the upcoming electronics lab, the taste of the canteen’s samosa, and the fact that jj here was not the current in Ohm’s law but the mysterious square root of 1-1.

"So," I wondered back then, "why would anyone bother multiplying by such a strange expression instead of using a good old rotation matrix?"

The professor moved on to another topic, the bell rang, and eje^{j\theta} quietly slipped into the dusty attic of my mind, along with Laplace transforms and contour integrals.

Fast forward: three decades later

Yesterday my young son, Ridit, said, " Baba, i would like to study the complex number. Because mostly the game engine uses Quaternions for elegantly handling rotation and for that to understand, i need the knowledge of complex algebra".

And then today, after coming back from school, he opened ChatGPT and showed me what he was speaking about - and I was astonished - yes... this is the case - and my mind took me more than 30 years ago, when my engineering college professor taught me this.

I totally forgot...

But NOW... i remember everything.

In the glow of a laptop screen, with Python code dancing across the terminal, I was plotting a simple 2D rotation. I tried the matrix way — it worked, as always.

Then i used...

z *= np.exp(1j * theta)

And there it was — the vector spun, clean and elegant, no sine or cosine in sight. A 30-year-old chalkboard came rushing back. My professor’s voice, muffled by time, echoed:

"Multiply by eje^{j\theta} and it rotates."

I finally felt the truth of it — the way Euler’s formula hides geometry inside algebra, the way the complex exponential is not just maths trickery but a perfect rotation operator.

The d茅j脿 vu

I sat back and smiled. In engineering college, it was just a formula to memorize. Three decades later, it was like meeting an old classmate and realizing they’d been brilliant all along.

The same equation, the same eje^{j\theta}, but now it wasn’t an exam answer — it was an elegant, almost poetic bridge between numbers and motion.

And somewhere, in some cosmic complex plane, I imagined my younger self and older self standing at the same point, separated by an angle \theta of 30 years, both connected by the same exponential arc.

Here's the python code for experimentation - visualising that multiplying by rotation matrix and by exp(j胃) produce the same effect.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Initial vector
x0, y0 = 1, 0.5
z0 = x0 + 1j * y0 # complex form

# Rotation speed
theta = np.pi / 60
frames = 120

# Rotation matrix
R = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])

# Set up figure
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
titles = ["Rotation via e^(j胃)", "Rotation via Matrix"]
plots = []

for ax, title in zip(axes, titles):
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
ax.set_aspect('equal', adjustable='box')
ax.axhline(0, color='gray', linewidth=0.5)
ax.axvline(0, color='gray', linewidth=0.5)
ax.set_title(title)
plots.append(ax.plot([], [], 'ro-', lw=2)[0])

# State variables
z = z0
v = np.array([x0, y0])


# Update function
def update(frame):
global z, v
# Complex method
plots[0].set_data([0, z.real], [0, z.imag])
z *= np.exp(1j * theta)

# Matrix method
plots[1].set_data([0, v[0]], [0, v[1]])
v = R @ v

return plots


# Animate
ani = FuncAnimation(fig, update, frames=frames, interval=50, blit=True)
plt.show()

And here's the screen recording of the above code.


Mathematics from decades ago can surprise you when it comes alive again on your screen.

When you teach a person, actually two people learn - here i am delving into calculus to show the light to my son...

1. The Problem

We have:

limx2x24x2\lim_{x \to 2} \frac{x^2 - 4}{x - 2}

If we try direct substitution (x=2x = 2):

(2)2422=440=00\frac{(2)^2 - 4}{2 - 2} = \frac{4 - 4}{0} = \frac{0}{0}

This is an indeterminate form — so the limit is not obvious.


Why it’s a Removable Discontinuity

The numerator x24x^2 - 4 factors:

x24=(x2)(x+2)x^2 - 4 = (x - 2)(x + 2)

So:

x24x2=(x2)(x+2)x2\frac{x^2 - 4}{x - 2} = \frac{(x - 2)(x + 2)}{x - 2}

For x2x \neq 2, the (x2)(x - 2) cancels:

x24x2=x+2\frac{x^2 - 4}{x - 2} = x + 2

The function behaves exactly like y=x+2y = x + 2 everywhere except at x=2x = 2.

At x=2x = 2, the original expression was undefined (division by zero), so there’s a hole in the graph — that’s the removable discontinuity.


Finding the Limit

Now that it’s simplified:

limx2x24x2=limx2(x+2)\lim_{x \to 2} \frac{x^2 - 4}{x - 2} = \lim_{x \to 2} (x + 2)






=2+2=4
= 2 + 2 = 4

So:

The limit is 4\boxed{\text{The limit is } 4}

If we define f(2)=4f(2) = 4, the discontinuity disappears and the function becomes continuous.


Visualizing

If you graph y=x24x2y = \frac{x^2 - 4}{x - 2}:

  • It looks like a straight line y=x+2y = x + 2

  • Except there’s an open circle at (2,4)(2, 4)
    That hole is the removable discontinuity.

Here's a visual representation of f(x).

The left top (the first one) shows the f(x) plotted.



Now let’s walk through L’H么pital’s Theorem for limits clearly and step-by-step.


The Problem L’H么pital Solves

Sometimes, when evaluating a limit, direct substitution gives an indeterminate form like:

  • 00\frac{0}{0}

  • \frac{\infty}{\infty}

These forms mean you can’t just plug in the value — but the limit might still exist.

Example:

limx2x24x2\lim_{x \to 2} \frac{x^2 - 4}{x - 2}

Direct substitution → 0/00/0.


Statement of L’H么pital’s Rule

If:

  1. limxaf(x)=0\lim_{x \to a} f(x) = 0 and limxag(x)=0\lim_{x \to a} g(x) = 0
    OR
    limxaf(x)=±\lim_{x \to a} f(x) = \pm\infty and limxag(x)=±\lim_{x \to a} g(x) = \pm\infty

  2. ff and gg are differentiable near aa (except possibly at aa)

  3. g(x)0g'(x) \neq 0 near aa

Then:

limxaf(x)g(x)=limxaf(x)g(x)\lim_{x \to a} \frac{f(x)}{g(x)} = \lim_{x \to a} \frac{f'(x)}{g'(x)}

provided the limit on the right exists or is ±\pm\infty.


How It Works (Example)

Example:

limx2x24x2\lim_{x \to 2} \frac{x^2 - 4}{x - 2}

Direct substitution → 0/00/0.

Step 1: Differentiate numerator and denominator separately:

f(x)=2x,g(x)=1f'(x) = 2x, \quad g'(x) = 1

Step 2: Apply L’H么pital’s Rule:

limx22x1=2(2)=4\lim_{x \to 2} \frac{2x}{1} = 2(2) = 4

Same answer we got earlier by factoring — but L’H么pital works even when factoring is messy.


Another Example with /\infty/\infty

limx3x2+5x7x24\lim_{x \to \infty} \frac{3x^2 + 5x}{7x^2 - 4}

Direct substitution → /\infty/\infty.

Differentiate top and bottom:

f(x)=6x+5,g(x)=14xf'(x) = 6x + 5,\quad g'(x) = 14x

Now:

limx6x+514x=limx6+5x14=614=37\lim_{x \to \infty} \frac{6x + 5}{14x} = \lim_{x \to \infty} \frac{6 + \frac{5}{x}}{14} = \frac{6}{14} = \frac{3}{7}

Notes and Common Mistakes

  • Only use when you get 0/00/0 or /\infty/\infty
    (For other indeterminate forms like 00 \cdot \infty, 11^\infty, \infty - \infty, you may first need algebraic manipulation.)

  • Apply the rule repeatedly if the first derivative still gives 0/00/0 or /\infty/\infty.

  • Remember: Differentiate top and bottom separately, never use the quotient rule here.


2. The Problem

Alright — let’s go step-by-step for

limx0sinxx\lim_{x \to 0} \frac{\sin x}{x}

Direct Substitution Check

If x=0x = 0,

sin(0)0=00\frac{\sin(0)}{0} = \frac{0}{0}

That’s an indeterminate form — so we need another method.

\lim_{x \to 0} \frac{\sin x}{x} = 1

Using L’H么pital’s Rule

We have 0/00/0 form. Differentiate top and bottom:

limx0cosx1=cos0=1

Final Answer:

                                                                        1

Visualization


See the plot at left column second from top.

3 . The problem

limx01x\lim_{x \to 0} \frac{1}{x}


First observation

If x=0x = 0, the expression is undefined because we can’t divide by zero.
So we check left-hand limit (LHL) and right-hand limit (RHL) separately.


Right-hand limit ( x0+x \to 0^+ )

Take xx as small positive numbers:

xx 1/x1/x
0.1 10
0.01 100
0.001 1000

As x0+x \to 0^+, 1/x+1/x \to +\infty.


Left-hand limit ( x0x \to 0^- )

Take xx as small negative numbers:

xx 1/x1/x
-0.1 -10
-0.01 -100
-0.001 -1000

As x0x \to 0^-, 1/x1/x \to -\infty.


Conclusion

The two one-sided limits are not equal:

limx0+1x=+\lim_{x \to 0^+} \frac{1}{x} = +\infty limx01x=\lim_{x \to 0^-} \frac{1}{x} = -\infty

Since they differ, the two-sided limit does not exist.


馃搶 Important: This is an example of an infinite discontinuity.

This is the third graph in the image attached earlier.

4. The problem - Jump Discontinuity

f(x)={1x<02x0

Visualization:

A step function shows a sudden jump — perfect for illustrating discontinuity.

The topmost in the right column of the image attached earlier


4. The Problem

The limit of

limx0sin(1x)\lim_{x \to 0} \sin\left(\frac{1}{x}\right)

is a classic example of a limit that does not exist.


Why it doesn’t exist

As x0x \to 0,

  • 1x+\frac{1}{x} \to +\infty when x0+x \to 0^+

  • 1x\frac{1}{x} \to -\infty when x0x \to 0^-

The sine function sin(t)\sin(t) oscillates between -1 and +1 infinitely often as t±t \to \pm \infty.

So near x=0x=0, sin(1x)\sin\left(\frac{1}{x}\right) oscillates wildly — no single number is approached.


Formal reasoning

We can try to take the right-hand limit:

Pick sequences:

xn=12nsin(1xn)=sin(2n)=0x_n = \frac{1}{2\pi n} \quad \Rightarrow \quad \sin\left(\frac{1}{x_n}\right) = \sin(2\pi n) = 0

and

yn=12n+/2sin(1yn)=sin(2n+2)=1y_n = \frac{1}{2\pi n + \pi/2} \quad \Rightarrow \quad \sin\left(\frac{1}{y_n}\right) = \sin\left(2\pi n + \frac{\pi}{2}\right) = 1

Both xn0x_n \to 0 and yn0y_n \to 0, but the function values approach different limits (0 and 1).
Hence, the limit does not exist.

5. The problem

Alright, let’s check if your function is continuous at x=1x = 1.

Given:

f(x)={x21if x<12if x=13xif x>1f(x) = \begin{cases} x^2 - 1 & \text{if } x < 1 \\ 2 & \text{if } x = 1 \\ 3 - x & \text{if } x > 1 \end{cases}

Step 1 – Left-hand limit (as x1x \to 1^-)

For x<1x < 1, f(x)=x21f(x) = x^2 - 1

limx1f(x)=121=0\lim_{x \to 1^-} f(x) = 1^2 - 1 = 0

Step 2 – Right-hand limit (as x1+x \to 1^+)

For x>1x > 1, f(x)=3xf(x) = 3 - x

limx1+f(x)=31=2\lim_{x \to 1^+} f(x) = 3 - 1 = 2

Step 3 – Compare limits

  • Left-hand limit = 0

  • Right-hand limit = 2
    Since 020 \neq 2, the limit at x=1x = 1 does not exist.


Step 4 – Conclusion

Continuity at x=1x = 1 requires:

limx1f(x)=f(1)\lim_{x \to 1} f(x) = f(1)

But here:

  • The two one-sided limits are not equal

  • So the function has a jump discontinuity at x=1x = 1

Final Answer:Not continuous at x=1x = 1.

Visualization

The bottom of the left column shows the graphical output of the function


6. The Problem

Let’s check step-by-step whether

f(x)={xsin(1x),x00,x=0f(x) = \begin{cases} x \sin\left(\frac{1}{x}\right), & x \neq 0 \\ 0, & x = 0 \end{cases}

is continuous at x=0x = 0.


Step 1: Continuity definition at a point

A function ff is continuous at x=0x = 0 if:

limx0f(x)=f(0)\lim_{x \to 0} f(x) = f(0)

That means:

  1. f(0)f(0) exists ✅

  2. The limit limx0f(x)\lim_{x \to 0} f(x) exists

  3. They are equal


Step 2: Check f(0)f(0)

From the definition:

f(0)=0f(0) = 0

Step 3: Find limx0f(x)\lim_{x \to 0} f(x)

When x0x \neq 0:

f(x)=xsin(1x)f(x) = x \sin\left(\frac{1}{x}\right)

We know that:

1sin(1x)1-1 \leq \sin\left(\frac{1}{x}\right) \leq 1

Multiplying through by xx (near x=0x=0):

xxsin(1x)x- |x| \leq x \sin\left(\frac{1}{x}\right) \leq |x|

Step 4: Apply the Squeeze Theorem

As x0x \to 0:

x0andx0- |x| \to 0 \quad \text{and} \quad |x| \to 0

So:

limx0xsin(1x)=0\lim_{x \to 0} x \sin\left(\frac{1}{x}\right) = 0

Step 5: Compare with f(0)f(0)

We have:

limx0f(x)=0=f(0)\lim_{x \to 0} f(x) = 0 = f(0)

Therefore, f(x)f(x) is continuous at x=0x = 0.

Visualisation



The squeeze theorem

The Squeeze Theorem (also called the Sandwich Theorem or Pinching Theorem) is a method in calculus for finding the limit of a function by “trapping” it between two simpler functions whose limits are known and equal.


Definition

If for all xx near aa (except possibly at aa itself), we have

g(x)f(x)h(x)g(x) \leq f(x) \leq h(x)

and

limxag(x)=Landlimxah(x)=L\lim_{x \to a} g(x) = L \quad \text{and} \quad \lim_{x \to a} h(x) = L

then

limxaf(x)=L\lim_{x \to a} f(x) = L

Intuition

Think of it like this:
If you trap f(x)f(x) between g(x)g(x) and h(x)h(x), and both of those are “squeezing” toward the same value LL as xx approaches aa, then f(x)f(x) must be squeezed to LL as well.


Example

Let’s prove:

limx0xsin(1x)=0\lim_{x \to 0} x \sin\left(\frac{1}{x}\right) = 0

We know:

1sin(1x)1-1 \leq \sin\left(\frac{1}{x}\right) \leq 1

Multiply all sides by x|x|:

xxsin(1x)x-|x| \leq x \sin\left(\frac{1}{x}\right) \leq |x|

As x0x \to 0:

limx0x=0andlimx0x=0\lim_{x \to 0} -|x| = 0 \quad\text{and}\quad \lim_{x \to 0} |x| = 0

By the Squeeze Theorem:

limx0xsin(1x)=0

Sunday, August 10, 2025

Hire after school, train for the job - Why's this model the most suitable for Bharat...

It will indeed bypass a lot of the distortions that India’s current college + reservation pipeline creates.

1. Why it would bypass reservation

Reservation applies to educational institutions and public sector jobs—but private sector hiring from 10+2 and training in-house isn’t bound by the same rules.

If companies don’t rely on government-affiliated degree programs, they sidestep entrance quotas entirely.

It removes the dependency on college “gatekeeping” where reservation heavily tilts admission.

2. Advantages

- Skill over certificate – You’re selecting for aptitude and trainability, not just paper degrees.

- Immediate industry relevance – Training would be tailored to current tech, tools, and methods, unlike outdated college syllabi.

- Cost savings – Companies save on hiring “already trained” graduates with mismatched skills and instead invest directly in relevant talent.

- Meritocracy – If hiring is based on an open aptitude test after 10+2, it can be far more merit-driven than current degree-based recruitment.

3. Challenges

Legal framework – The Apprentices Act and labour laws in India would need tweaks to allow large-scale recruitment at 18 without degree prerequisites.

Social acceptance – Many parents still see a “degree” as essential social capital, even if the job is well-paying.

Mobility – Without a degree, employees might face trouble if they later want to move to other companies or go abroad (though in tech, experience often trumps degree).

Training investment risk – Companies spend resources on training, and the trainee could leave for another employer after gaining skills.

4. Possible models in India

German-style dual vocational training – Students split time between classroom theory (private institutes or online) and in-company apprenticeships.

Company-backed skill universities – Firms like TCS, Infosys, or Mahindra could run accredited programs that give both skills and a formal qualification.

Industry-standard aptitude exams – Private “job boards” could run standardised tests at 18, letting top scorers directly enter company training tracks.

If this became mainstream, the traditional degree + reservation pathway would lose relevance, and hiring would shift to skills-first meritocracy.

But it would need strong industry coalition and a public shift in mindset—right now, most of India still sees “college degree” as non-negotiable, even if the degree adds little value.

Friday, August 8, 2025

The story of Pybinding - a python wrapper around C++...

 Pybinding isn't a single, monolithic tool, but rather a concept that has been realized by several different libraries. The most prominent and widely used among them is pybind11. The story of pybind11 is a testament to the enduring need for high-performance computing in Python and the elegant solutions that can arise from a desire for simplicity and efficiency.

The story starts with a common problem: Python is a fantastic language for rapid prototyping, data analysis, and orchestrating complex tasks. However, when it comes to raw computational speed, especially for number-crunching or highly parallelized operations, it can fall short. C++ and other compiled languages, on the other hand, excel in these areas. The question was, how do you get the best of both worlds? How do you write the performance-critical parts of your application in C++ while still enjoying the development speed and ecosystem of Python?

The answer was to create a "binding" – a bridge that allows Python to call C++ code as if it were native Python. Early efforts in this space, such as Boost.Python, were powerful but often came with a steep learning curve and significant compilation overhead. They were a bit like using a sledgehammer to crack a nut – effective, but perhaps a bit unwieldy for many use cases.

This is where the next chapter of the story begins, with the emergence of pybind11. The creator of pybind11, Wenzel Jakob, had a vision for a library that would be:

  • Lightweight and Header-Only: No need to link against a large library. You just include the headers, and the magic happens at compile time.

  • Easy to Use: The syntax should feel "Pythonic" and intuitive, allowing developers to create bindings with minimal boilerplate code.

  • Efficient: The generated code should be fast and have a small binary footprint.

  • Modern: It should fully embrace modern C++ standards, like C++11 and beyond, to take advantage of features like move semantics and templates.

Pybind11 was born from this vision, and it quickly gained traction. It told a new story about how C++ and Python could work together. Instead of a cumbersome, complex process, creating a Python wrapper became a straightforward task.

The story of using pybind11 often goes something like this:

The Setup: A scientist or developer has a C++ library with a highly optimized algorithm. Let's say it's a function that performs a complex matrix multiplication. They want to use this function from their Python scripts, where they are handling data loading, visualization, and other tasks.

The Binding: They write a small C++ file that acts as the "wrapper." This file includes the pybind11 headers and uses its simple syntax to expose the C++ function to Python. They define a Python module, give their C++ function a Python-friendly name, and specify the types of arguments it takes. Pybind11 automatically handles the conversion between Python's data types (like NumPy arrays) and C++'s native types (like std::vector or Eigen matrices).

The Compilation: Using a build system like CMake, they compile this wrapper file. The result is a shared library (.so or .dll) that Python can import.

The Payoff: Back in their Python script, they can now simply import the newly created module and call the C++ function directly. The performance-critical work is handled by the blazing-fast C++ code, while the rest of the application remains in the flexible and easy-to-manage world of Python.

So... here we go...

My exploration of Pybinding11 to refactor one of my projects called FactoryDesignPattern.

Here's the source code...

/*

* Food.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef FOOD_H_

#define FOOD_H_

#include <string>


using namespace std;


class Food {

public:

virtual string getName() = 0;


virtual ~Food(){


}

};



#endif /* FOOD_H_ */



/*

* Biscuit.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef BISCUIT_H_

#define BISCUIT_H_


#include "Food.h"


class Biscuit: public Food {

public:

Biscuit();

string getName();

~Biscuit();

};


#endif /* BISCUIT_H_ */


/*

* Biscuit.cpp

*

* Created on: Mar 10, 2021

* Author: som

*/

#include <iostream>

#include "Biscuit.h"

using namespace std;



Biscuit::Biscuit() {

// TODO Auto-generated constructor stub

cout<<"Biscuit is made..."<<endl;


}


Biscuit::~Biscuit(){}



string Biscuit::getName(){

return "It's a Biscuit";

}


/*

* Chocolate.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef CHOCOLATE_H_

#define CHOCOLATE_H_


#include <iostream>

#include "Food.h"


class Chocolate: public Food {

public:

Chocolate();

virtual ~Chocolate();

string getName();

};



#endif /* CHOCOLATE_H_ */


/*

* Chocolate.cpp

*

* Created on: Mar 10, 2021

* Author: som

*/


#include "Chocolate.h"



Chocolate::Chocolate() {

// TODO Auto-generated constructor stub

cout<<"Chocolate is made..."<<endl;


}


Chocolate::~Chocolate() {

// TODO Auto-generated destructor stub

}


string Chocolate::getName(){

return "It's a Chocolate";

}


/*

* Factory.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef FACTORY_H_

#define FACTORY_H_


#include <pybind11/pybind11.h>

#include <iostream>

#include <string>


#include "Biscuit.h"

#include "Chocolate.h"


using namespace std;


class Factory{

public:

static Factory* instance;

static Factory* getInstance();


Food* makeFood(const string& type);


private:

Factory(){}


// Delete copy constructor & assignment operator (Singleton pattern)

Factory(const Factory&) = delete;

Factory& operator=(const Factory&) = delete;

};

//Factory* Factory:: instance = NULL;



#endif /* FACTORY_H_ */


/*

* Factory.cpp

*

* Created on: Jan 30, 2025

* Author: som

*/

#include "Factory.h"

Factory* Factory::instance = NULL;


Factory* Factory:: getInstance(){

if(Factory::instance == NULL){

Factory::instance = new Factory();

}

return Factory::instance;

}


Food* Factory::makeFood(const string& type){

if(type.compare("bi") == 0){

return new Biscuit();

}

if(type.compare("ch") == 0){

return new Chocolate();

}


return NULL;

}




//bindings.cpp


#include <pybind11/pybind11.h>

#include <memory>


#include "Food.h"

#include "Factory.h"

#include "Biscuit.h"

#include "Chocolate.h"


namespace py = pybind11;


PYBIND11_MODULE(libfoodfactory, m) {

py::class_<Food, std::shared_ptr<Food>>(m, "Food")

.def("get_name", &Food::getName);


py::class_<Biscuit, Food, std::shared_ptr<Biscuit>>(m, "Biscuit")

.def(py::init<>());


py::class_<Chocolate, Food, std::shared_ptr<Chocolate>>(m, "Chocolate")

.def(py::init<>());


m.def("make_food", [](const std::string& type) -> std::shared_ptr<Food> {

Food* f = Factory::getInstance()->makeFood(type);

if (!f) throw std::runtime_error("Unknown food type");

return std::shared_ptr<Food>(f); // manage memory in Python

});

}


Here's the CMakeLists.txt


cmake_minimum_required(VERSION 3.10)


# Set some basic project attributes

project (FactoryPattern_pybind)


set(CMAKE_CXX_STANDARD 14)


# Set the prefix path to where pybind11 is installed,

# allowing CMake to find its configuration files.

# This assumes pybind11 was installed via pip.

list(APPEND CMAKE_PREFIX_PATH "/home/som/.local/lib/python3.8/site-packages")


# Find the pybind11 package. The REQUIRED keyword ensures

# the build fails if the package isn't found.

find_package(pybind11 REQUIRED)


# Add the shared library (MODULE is for Python extensions)

add_library(foodfactory MODULE

Biscuit.cpp

Chocolate.cpp

Factory.cpp

bindings.cpp

)


# Set include directories for your source files.

# No need to add pybind11's include path here, as it's

# handled by the pybind11::pybind11 target.

target_include_directories(foodfactory PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})


# Link the library to the pybind11 provided target.

# This ensures all necessary compiler flags and include paths

# from pybind11 are used.

target_link_libraries(foodfactory PRIVATE pybind11::pybind11)



The story of pybind11 is not just about a technical tool ; it's about

a paradigm shift. It showed that the barrier between C++ and Python

could be lowered significantly, making it easier for developers to

leverage the strengths of both languages. It's a story of how a

well-designed, modern library can solve a long-standing problem

and become the de-facto standard in its domain.


Enjoy...

Read my other exploration regarding Python and C++ bindings.

Here we go...

Let's start with SWIG...




And now let's delve into Boost.Python...