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. Thenmdemo (§14.2) is worth doing live — seeing__demo_MOD_plainbesidetidymakes 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-02params_t).
Misconceptions to preempt
- "
real(dp)andreal(c_double)are interchangeable, so it doesn't matter." (Same value on your machine;c_doubleis 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
logicalmaps to C's_Bool." (No — uselogical(c_bool).) - "If it compiles, the interface is right." (The bug is between languages; no compiler sees both sides.)
- "You can link a Fortran
programand a Cmaintogether." (Two entry points — duplicatemain.) - "Pass the 2-D array and the languages will sort out the layout." (They won't — it silently transposes.)
A live demonstration (~10 minutes)
- 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 cleanbind(c)symbol. - Build
example-01(Fortran calls Cvec3_norm) and show13.00. Then deletevaluefrom the interface, rebuild, and show the garbage/crash. Restore it. This ten-second before/after teaches the value rule better than a paragraph. - 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_bindingkinds (§14.1). - 10 min:
bind(c), linkage, thenmdemo (§14.2). - 20 min: calling C from Fortran + the
valuerule, 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 withc_double. - Ch.6
intent, explicit-shape vs assumed-shape arrays — the array-argument forms. - Ch.11
target/contiguous/pointers — needed forc_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.