Tag Archives: freepascal

story about linking Pascal and Oberon.

I prefer to write programs in Oberon when it does not require too many extra efforts. It requires too many extra efforts simply because it is not widely used, and this often leads to the community is fragmented and small. This explains why we don’t have the huge code base of Oberon sources, and the regular Oberon developer always has challenges, regular Python programmer does not have. Oberon developer needs to change existing libraries in order to compile them with different compilers, or may be prepare wrappers in order to compile those libraries. It is often necessary to prepare bindings to C code, or just translate some code by hand, just because no one before have dote it.

I don’t have yet good skills in programming graphical interfaces in Oberon, however you can find an example of GTK program at my github page.

I was using Lazarus/FreePascal to develop graphical applications, and it has one clear and important advantage for me – interface does not depend on the backend widget suite. For instance, I have recompiled the same program so that it would draw itself by using Qt, or GTK, or even native WinAPI on Windows.

That lead me to the idea to combine some Pascal and Oberon code together, and to call Oberon code handlers from the LCL application. Oberon compiler I used, ooc, has a C backend, so the stary begins.

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