Chapter 14 — Teaching Notes

One-line purpose. Give students a portable, standard way to make Fortran and C call each other (iso_c_binding + bind(c)), with the by-value/by-reference rule and the column-major/row-major trap as the two ideas that must stick — because both fail silently.

Key ideas to emphasize

  • The C ABI is the universal socket. Frame interop not as "Fortran talks to C" but as "Fortran gets a C linkage, and therefore can be called by C, C++, Python, Julia, Rust — anything that dials a C function." This reframing (§14.2 Threshold Concept) is what motivates the whole chapter and sets up Ch.15.
  • The value/reference rule is the crux. Scalars from C need value; arrays and structs do not. Drill it until automatic. The killer property (§14.3 Find-the-Bug, CS-01) is that getting it wrong compiles and then lies — an address read as a value, or a copy the caller never sees.
  • Column-major vs row-major (§14.5). The single most expensive misunderstanding in mixed-language scientific code. Emphasize: no bytes are wrong, the memory is merely indexed oppositely; the fix is a layout contract (u(i+1,j+1) = u[i+j*nx]), never a per-call transpose (Ex.14.20 quantifies the cost).
  • bind(c) defeats name mangling. The nm demo (§14.2) is worth doing live — seeing __demo_MOD_plain beside tidy makes it concrete in one command.
  • Interoperable types must stay in lockstep with the C struct, and bind(c) makes the padding match for free (§14.5, CS-02 params_t).

Misconceptions to preempt

  • "real(dp) and real(c_double) are interchangeable, so it doesn't matter." (Same value on your machine; c_double is the one defined to match C and documents intent.)
  • "Fortran strings are C strings." (No — C strings are null-terminated; append/scan c_null_char.)
  • "A default logical maps to C's _Bool." (No — use logical(c_bool).)
  • "If it compiles, the interface is right." (The bug is between languages; no compiler sees both sides.)
  • "You can link a Fortran program and a C main together." (Two entry points — duplicate main.)
  • "Pass the 2-D array and the languages will sort out the layout." (They won't — it silently transposes.)

A live demonstration (~10 minutes)

  1. Compile the two-procedure module from §14.2 and run nm demo.o | grep -E 'plain|tidy'. Let students see the mangled name vs the clean bind(c) symbol.
  2. Build example-01 (Fortran calls C vec3_norm) and show 13.00. Then delete value from the interface, rebuild, and show the garbage/crash. Restore it. This ten-second before/after teaches the value rule better than a paragraph.
  3. If time: build CS-02's bridge, then move the C driver's hot spot with row-major indexing and watch the physics silently relocate.

Class-time budget (~75–90 min, advanced chapter)

  • 10 min: the C ABI framing + iso_c_binding kinds (§14.1).
  • 10 min: bind(c), linkage, the nm demo (§14.2).
  • 20 min: calling C from Fortran + the value rule, with the live bug demo (§14.3).
  • 15 min: calling Fortran from C + the mixed compile/link (§14.4).
  • 20 min: arrays (the column-major trap), strings (null terminator), structs (§14.5).
  • 10 min: the project shim + how it becomes a library (Checkpoint / CS-02).

Prerequisites to review

  • Ch.3 kinds (selected_real_kind, dp) — needed to contrast with c_double.
  • Ch.6 intent, explicit-shape vs assumed-shape arrays — the array-argument forms.
  • Ch.11 target/contiguous/pointers — needed for c_loc/c_f_pointer.
  • Ch.9 derived types (field_t) — needed for the interoperable-type section and the checkpoint.
  • Basic C literacy (reading a prototype, const, double *) — assign a 15-minute K&R skim if the class is Fortran-only.

Connections

Back: Ch.3, 5, 6, 9, 11. Forward: Ch.15 (f2py — this chapter is its foundation; make the dependency explicit), Ch.16 (linking ecosystem libraries), Ch.21 (LAPACK via a C-style interface). The heat-solver anchor advances to a C-callable library here.