docs
Tutorials
Converting a C Model

Tutorial: Converting a C Model

This tutorial provides a step-by-step guide to converting a simulation model written in C into a Functional Mock-up Unit (FMU) using the Jingongo SDK.

The process is very similar to converting a Python model. The SDK packages your local C source files, uploads them to the Jingongo cloud platform, and orchestrates the remote compilation and packaging into a final .fmu file.

Prerequisites

Before you begin, please ensure you have completed the following steps from our "Getting Started" guide:

  1. Installed the SDK: pip install jingongo-framework
  2. Generated and configured your API Key: The JINGONGO_API_KEY environment variable must be set.

The Example C Model

For this tutorial, we will use the sample c_identity_block_model located in the examples/example_models/ directory of our repository. This is a simple "pass-through" model that demonstrates the required file structure and configuration.

1. The C Source Code

A C-based model for Jingongo typically requires at least two files: a header (.h) and a source (.c) file. These files must implement a specific interface that the Jingongo engine can call into.

model.h (The Header File) This file defines the data structure that holds your model's state, inputs, outputs, and parameters.

// examples/example_models/c_identity_block_model/model.h
 
#ifndef MODEL_H
#define MODEL_H
 
// This struct defines the memory for our model.
// It holds all variables the simulation engine needs to interact with.
typedef struct {
    // Inputs
    double input_value;
 
    // Outputs
    double output_value;
 
    // Parameters
    double gain;
 
} ModelData;
 
#endif // MODEL_H

model.c (The Source File) This file contains the core logic of your simulation. It implements functions to initialize the model and to perform a "step" in the simulation.

// examples/example_models/c_identity_block_model/model.c
 
#include "model.h"
 
// The 'do_step' function is the heart of the simulation.
// It is called at each time step by the Jingongo engine.
void do_step(ModelData* data, double dt) {
    // This model's logic is very simple:
    // output = input * gain
    data->output_value = data->input_value * data->gain;
}
 
// The 'initialize' function is called once at the beginning.
// It sets the initial state of the model.
void initialize(ModelData* data) {
    // Set default starting values
    data->input_value = 0.0;
    data->output_value = 0.0;
    // 'gain' is a parameter, so its value will be set by the
    // configuration and does not need to be initialized here.
}

2. The Jingongo Configuration File

The .jingongo.yml file is crucial. It acts as the "manifest" for your model, telling the Jingongo engine everything it needs to know about your C code, including its variables and parameters.

.jingongo.yml
# examples/example_models/c_identity_block_model/.jingongo.yml

model:
  # Basic metadata for your model
  model_name: "C_Identity_Block"
  version: "1.0.1"
  description: "A simple pass-through model implemented in C."
  language: "c"

  # Define the variables the outside world can interact with
  inputs:
    - name: "input_value"
      type: "Real" # Corresponds to 'double' in C

  outputs:
    - name: "output_value"
      type: "Real" # Corresponds to 'double' in C

  parameters:
    - name: "gain"
      type: "Real"
      default: 1.0 # The default value if not overridden

      The Conversion Script
The Python script below orchestrates the entire conversion process. It points the Jingongo SDK to your local model directory, and the SDK handles the rest.
This script is available at examples/03_convert_c_model.py in the repository.
# examples/03_convert_c_model.py
import os
import sys
import json
import logging
from pathlib import Path
 
# Make the SDK importable when running from the repo root
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../src')))
 
from jingongo import Jingongo
 
# --- Configuration ---
JINGONGO_API_BASE_URL = "https://jingongo-backend-api-723715926581.us-central1.run.app"
 
def main():
    """
    Demonstrates converting a local C-based model into an FMU.
    """
    print("--- Tutorial: Converting a C model to an FMU ---")
    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
    
    api_key = os.environ.get("JINGONGO_API_KEY")
    if not api_key:
        print("\n❌ Error: Please set the JINGONGO_API_KEY environment variable.")
        return
 
    try:
        # 1. Initialize the Jingongo client
        client = Jingongo(JINGONGO_API_BASE_URL, api_key, verbose=True)
 
        # 2. Define the path to the local model directory
        c_model_path = Path(__file__).parent / "example_models" / "c_identity_block_model"
        
        if not c_model_path.exists():
            raise FileNotFoundError(f"❌ Model directory not found: {c_model_path.resolve()}")
 
        print(f"\n🚀 Starting conversion for model at: {c_model_path}")
        
        # 3. Call the core conversion method
        # The SDK will zip the directory, upload it, and start the conversion.
        # It automatically reads the .jingongo.yml for metadata.
        c_job = client.convert_to_fmu(
            project_path=c_model_path,
            language="c" # We specify the language here
        )
        
        print("\n✅ C Conversion Job Finished!")
        print("Backend Response:")
        print(json.dumps(c_job, indent=2))
 
    except Exception as e:
        print(f"\n❌ An error occurred during conversion: {e}")
 
if __name__ == "__main__":
    main()

How to Run It

  1. Make sure your JINGONGO_API_KEY is set in your terminal.
  2. Navigate to the root of the repository.
  3. Run the script:
 
python -m examples.03_convert_c_model

You will see the SDK log its progress as it packages and uploads your C model. The cloud engine will then compile it and package it into an FMU, with real-time status updates appearing in your console.