erzahlung uber: interfacing freepascal code with Oberon (oo2c)

Let’s write a minimal module with one exported function in Oberon:

MODULE m; PROCEDURE add*(a, b : INTEGER): INTEGER; BEGIN RETURN a + b; END add; END m.

We even can compile it now with oo2c

$ oo2c m.Mod

and get directories obj and sym.

We may now compile obj/m.c

and get an object m.o

gcc -Iobj -I/local/oo2c/lib/oo2c/src -I/local/oo2c/lib/oo2c/obj -c obj/m.c

Now we need a pascal wrapper to bind it.

Let’s call it mbind.pas

unit mbind; {$link m.o} (*oo2c objs to link*) {$link RT0.o} {$link Object.o} {$link Exception.o} {$link HashCode.o} {$linklib c} interface uses CTypes; function m__add(a, b : ctypes.cint16) : ctypes.cint16; cdecl; external; (* /local/oo2c/lib/oo2c/obj/C.oh typedef OOC_INT16 C__shortint; *) implementation end.

We need to tell compiler explicitly which object files to link.

m.o is the object file we get by compiling obj/m.c

Other files are the minimal oo2c rtl which needs to be linked.

We also need to link to libc, because oo2c works by compiling via C.

Function name is m__add because oo2c translates m.add to C as m__add

Note, that implementation section is empty, and fpc does not issue an error because the function marked as external.

Eventually, let’s write a main module to call the Oberon function.

program m0; uses mbind; var i : integer; begin i := m__add(20, 3); writeln (i); end.

Neither fpc nor oo2c do not need a make file.

FreePascal compiler, as well as Oberon can itself resolve module dependencies.

For example, I do not need to write a makefile where I compile first mbind.pas and get mbind.o and link it during the next step.

However, in this case I’d like to write a make file.

IPATH = -Iobj -I/local/oo2c/lib/oo2c/src -I/local/oo2c/lib/oo2c/obj LPATH = /local/oo2c/lib/oo2c/obj GCC = /usr/bin/gcc OO2C = /local/oo2c/bin/oo2c FPC = /local/fpc/bin/fpc all: $(OO2C) m.Mod $(GCC) $(IPATH) -c obj/m.c $(FPC) -Fo$(LPATH) -Fo. m0.pas clean: rm *.o rm *.ppu

I usually use custom fpc I compiled from subversion, and I prefer to keep my software in /local

LPATH is the path where oo2c main rtl objects are located, so fpc can find and link RT0.o, Exceptions.o, Object.o and HashCode.o.

So, first oo2c compiles the m module to c.

Then gcc compiles it to object file.

Then fpc compiles the main module.

And now enjoy:

$ ./m0 23

und so weiter