# How to call Modula-3 procedures from a C program?

Calling Modula-3 from C is tricky because M3 has a more elaborate run-time environment. The simplest solution is to make the main program M3 and then call C via EXTERNAL routines. Calling back into M3 is then relatively straightforward.

Here's an example. It calls the C code to lodge the identity of the M3 procedure to be called back which avoids having to know the actual name used by the linker.

First a little M3 module to be called from C (M3code), then a C module called by the M3 main and calling the M3 module (Ccode), and finally the main program (Main):

    (* M3code.i3 *)

    INTERFACE M3code;
    IMPORT Ctypes;
    PROCEDURE put (a: Ctypes.char_star);
    END M3code.

    (* M3code.m3 *)

    UNSAFE MODULE M3code;
    IMPORT Ctypes, IO, M3toC;

    PROCEDURE put (a: Ctypes.char_star) =
      BEGIN
        IO.Put (M3toC.StoT (a) & "\n");
      END put;

    BEGIN
    END M3code.

    (* Ccode.i3 *)

    <*EXTERNAL*> INTERFACE Ccode;
    IMPORT Ctypes;
    PROCEDURE set (p: PROCEDURE (a: Ctypes.char_star));
    PROCEDURE act (a: Ctypes.char_star);
    END Ccode.

    /* Ccode.c */

    typedef void (*PROC)();
    static PROC action;

    void set (p)
      PROC p;
      {
        action = p; /* register the M3 procedure */
      }

    void act (a)
      char *a;
      {
        action (a); /* call the M3 procedure */
      };

    (* Main.m3 *)

    UNSAFE MODULE Main;

    IMPORT Ccode, M3code, M3toC;

    BEGIN
      Ccode.set (M3code.put);
      Ccode.act (M3toC.TtoS ("Hello world"));
    END Main.

    (* m3makefile *)

    import(libm3)

    interface ("Ccode")
    c_source ("Ccode")
    module ("M3code")
    implementation("Main")
    program("mixed")