#  Building an F# Control Plane with a C Data Plane on Linux

Modern software systems often separate **control logic** from **high-performance execution logic**. This design is common in networking, distributed systems, operating systems, storage engines, and embedded software.

In this project, we build a simple Linux application that demonstrates this architectural pattern using:

- **F#** as the **Control Plane**
- **C** as the **Data Plane**
- **P/Invoke** for interoperability
- **Linux Shared Libraries (.so)**

Although the example is intentionally simple, the same design scales to much larger systems.

---

# Why Separate Control Plane and Data Plane?

Different programming languages excel at different tasks.

| Control Plane | Data Plane |
|---------------|------------|
| User interaction | High-performance computation |
| Input validation | Native execution |
| Business logic | Memory-efficient processing |
| Workflow orchestration | Optimized algorithms |
| F# | C |

In this project:

- F# collects user input.
- The terrain data is stored in a managed array.
- The array is passed directly to native C.
- C prints the terrain grid.

This demonstrates a clean separation of responsibilities.

---

# Project Architecture

The project consists of two independent components.

## Control Plane

Responsibilities:

- Read terrain dimensions
- Read elevation values
- Store data in a managed array
- Invoke native code

Technology:

- F#
- .NET 8

---

## Data Plane

Responsibilities:

- Receive terrain data
- Traverse the array
- Print formatted output

Technology:

- C
- GCC
- Shared Library (.so)

---

# Project Structure

```text
terrain_grid/
│
├── control_plane/
│   ├── Program.fs
│   ├── Terrain.fs
│   └── control_plane.fsproj
│
├── data_plane/
│   ├── terrain.c
│   ├── terrain.h
│   └── libterrain.so
│
└── README.md
```

---

# The Control Plane (F#)

The control plane is responsible for gathering input and forwarding it to the native library.

A simplified version:

```fsharp
let terrain = Array.zeroCreate<double>(rows * cols)

Terrain.display_terrain(
    terrain,
    rows,
    cols)
```

Notice that the F# code never performs the display itself.

Its only responsibility is orchestration.

---

# Calling Native C with P/Invoke

The bridge between managed and native code is created with `DllImport`.

```fsharp
[<DllImport("libterrain.so",
    CallingConvention = CallingConvention.Cdecl)>]
extern void display_terrain(
    double[] terrain,
    int rows,
    int cols)
```

P/Invoke automatically marshals the managed array into a native pointer that the C library can consume.

---

# The Data Plane (C)

The C library receives a pointer to the terrain array and prints the values.

```c
void display_terrain(
    const double* terrain,
    int rows,
    int cols)
{
    printf("%8.2f",
           terrain[i * cols + j]);
}
```

Because the array is stored contiguously, indexing is straightforward.

---

# Why Use a One-Dimensional Array?

Although the terrain logically represents a matrix, it is stored as a linear array.

Advantages include:

- Contiguous memory
- Better cache locality
- Easier interoperability
- Simpler pointer arithmetic
- Lower overhead

The index calculation is:

```text
index = row * columns + column
```

This technique is widely used in:

- Scientific computing
- Image processing
- Game engines
- Embedded software
- Numerical libraries

---

# Building the Shared Library

Compile the native library using GCC.

```bash
gcc -shared -fPIC terrain.c -o libterrain.so
```

---

# Building the F# Project

```bash
dotnet build
```

Run:

```bash
dotnet run
```

---

# Sample Output

```text
Rows : 2
Cols : 2

Elevation [0][0] : 2
Elevation [0][1] : 3
Elevation [1][0] : 4
Elevation [1][1] : 5

Terrain Grid (Elevation in meters)
----------------------------------
    2.00    3.00
    4.00    5.00
```

---

# What This Example Demonstrates

This small application introduces several important concepts.

- F# to C interoperability
- Linux shared libraries
- P/Invoke
- Managed and native memory interaction
- Control Plane / Data Plane architecture
- One-dimensional representation of matrices

---

# Where This Pattern Is Used

The same architecture appears in many production systems.

- Network packet processing
- Linux networking subsystems
- Storage engines
- Embedded firmware
- Robotics
- High-performance computing
- Scientific simulations
- CAD applications
- GIS software
- Image processing pipelines

The complexity may increase, but the architectural principle remains the same.

---

# Possible Extensions

This project can easily be expanded by adding features such as:

- Terrain statistics
- Height normalization
- Gradient calculation
- Heat map generation
- Terrain smoothing
- File import/export
- CSV support
- Binary terrain format
- OpenGL visualization
- GIS integration

---

# Conclusion

This project demonstrates how managed and native languages can work together effectively.

F# provides expressive and concise application logic, while C delivers predictable native execution. By combining the two through P/Invoke, developers can build applications that are both productive and performant.

Although the terrain grid application is intentionally small, it illustrates a design pattern that scales to much larger systems in systems programming, embedded development, and high-performance computing.

---

## GitHub Repository

**terrain_grid**

https://github.com/aj333git/Civil_Mech_apps/tree/main/terrain_grid

---


