TYPED CONVERSIONS

Separate C module exports

Give your C project a header and a separately compiled source file for each Python module, together with an exact interface manifest.

Mode: Typed conversion. This export uses the current Typed conversion result. Runtime conversion continues to use single-file output. Exporting does not compile or execute your source.

Export from the workspace

  1. Open the Python modules and check their logical module identities in the source bundle.
  2. Select Transpile → Typed and run Transpile.
  3. Choose File → Export C Modules…. Select a .zip destination in the themed file chooser.
  4. Extract the archive into its own directory. Include the desired module header in your C caller and compile each generated .c file separately.

The command is disabled until a fresh Typed conversion is available. Source and identity edits retire export access immediately. If the workspace changes while an archive is being prepared, it is not published and an existing destination stays intact.

Save C still saves the single-file result. The Generated C viewer, ForgeLens, and the IDE Compile action continue to use that result. Module exports do not change its destination.

Archive contents

FilePurpose
One pcf_…​.h per moduleExact declarations for its exported source functions.
One pcf_…​.c per moduleIts converted function bodies and the internal helpers they need.
pycforge_types.hShared C includes and any generated record declarations.
pycforge_abi.jsonModule/file mapping, function symbols, complete C parameter declarations, record field layouts, ownership, dependencies and source/header hashes.
BUILD.txtSeparate compilation and linking instructions.

Filenames use a digest of the module identity plus a readable suffix. Use the manifest to identify each header and source. All source functions are exported; support helpers retain internal linkage. A function beginning with an underscore is not automatically hidden.

Complete square-function example

Keep the module identity main for this example.

def square(value: int) -> int:
    return value * value

The same export can be created through the Python API. Run this script in a directory where you want to save the archive.

from pathlib import Path
from pycforge import ConversionRequest, PythonToCConverter, export_c_modules

source = "def square(value: int) -> int:\n    return value * value\n"
result = PythonToCConverter().convert(ConversionRequest.from_source(source))
if result.generated_c is None:
    raise RuntimeError("Conversion failed; inspect result.diagnostics")
exported = export_c_modules(result)
Path("c-modules.zip").write_bytes(exported.zip_bytes())

Extract c-modules.zip, then save this separate caller as caller.c beside the exported files.

#include <inttypes.h>
#include <stdio.h>
#include "pcf_0d6e4079e36703eb_main.h"

int main(void)
{
    printf("%" PRId64 "\n", square(12));
    return 0;
}

For GCC or Clang, compile the generated source to an object, then link it with your caller:

gcc -std=c11 -c pcf_0d6e4079e36703eb_main.c -o square.o
gcc -std=c11 caller.c square.o -o square-demo

Run ./square-demo on Linux/macOS or .\square-demo.exe in Windows PowerShell. It prints 144. For a larger bundle compile every generated .c once and link all the objects. Include -lm where your toolchain requires it for math helpers.

Record interfaces

A supported record parameter or return becomes a struct value in the exported function declaration. The module header includes pycforge_types.h, so the caller sees the complete layout. The manifest's record_types lists the generated struct and field names and their exact C types.

For this standalone example, keep the module identity main. Transpile and export it in a separate directory from the square example.

class Point:
    x: int
    y: int

    def __init__(self, x: int, y: int) -> None:
        self.x = x
        self.y = y

def make_point(x: int, y: int) -> Point:
    return Point(x, y)

def sum_point(point: Point) -> int:
    return point.x + point.y

Save the following as caller.c beside this example's exported files. Compile and link using the commands above. It prints 7.

#include <inttypes.h>
#include <stdio.h>
#include "pcf_0d6e4079e36703eb_main.h"

int main(void)
{
    Point point = make_point(3, 4);
    printf("%" PRId64 "\n", sum_point(point));
    return 0;
}

The returned struct owns its inline scalar values. Passing it copies those values; no allocation, disposal call, or free is required. If you construct a struct in C, initialize every field with a value valid for the corresponding typed field. Keep the generated declarations intact and use the manifest's names for your own source bundle.

Direct Python imports can share a record type across supplied modules. The shared type header contains one complete struct layout for each declaring class; aliases use the same type. A record-only module has a source/header pair with no exported functions. See the multi-module geometry example. Function-call dependencies remain listed per module; record layouts are available through the shared type header.

Caller contracts and limits