Forum > General

Linking question

<< < (2/2)

jollytall:
Thanks for the clarification.

Khrys:
The reason why  cmem  et al. need to be placed at the beginning of the main unit's  uses  section is a consequence of the way FPC handles unit initialization and involves no magic at all.
The unit tree is traversed left-to-right and depth-first, meaning that in your example...


--- Code: Text  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---u0|+--------------+|              |u1             u2|+-------+|       |u11     u12
...the order of initialization is as follows:  u11, u12, u1, u2, u0
More specifically, the units'  initialization  blocks are executed in that order. Looking at  cmem...


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Initialization  GetMemoryManager (OldMemoryManager);  SetMemoryManager (CmemoryManager);
...you'll see that all it does is replace the RTL's global  TMemoryManager  record, which  GetMem, FreeMem  (and class constructors/destructors) all rely on. To make sure that all other units (including their  initialize  blocks) use the new memory manager, this code needs to run as early as possible - hence the placement at the very beginning in the  uses  clause of the root unit.


In the case of multiple units defining a function with the same name, it's important to know two things:

FPC allows extensive name shadowing, meaning that the same identifier may refer to different things in different scopes

For example, the  objpas  unit defines  TIntegerArray  as a fixed-size array with a total size of 960 MiB (for legacy reasons I assume). If you don't find this useful (I don't), you're free to redefine it as e.g.  type TIntegerArray = array of Integer;  and the compiler won't complain - it'll simply use the most recently given definition. This also applies to units in the  uses  clause:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---uses  u2, u12;   foo(); // Refers to u12.foo

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---uses  u12, u2;   foo(); // Refers to u2.foo
It's of course also possible to explicitly refer to an implementation by prepending the unit name, e.g.  u12.foo();

FPC mangles function names in a way that includes the unit name (among other things)

This makes FPC-generated code more powerful in the sense that source-level identifiers don't have to be unique even across objects files / translation units. For example, the  Format  function in  SysUtils  is referred to by the symbol  SYSUTILS_$$_FORMAT$ANSISTRING$array_of_const$$ANSISTRING  by the linker instead of its literal name.

Navigation

[0] Message Index

[*] Previous page

Go to full version