Forum > General
Linking question
jollytall:
It is clear that if I have a unit u0 (or the main program) and it refers (in the interface or implementation section) two units u1 and u2, u1 can only use the subroutines (and types, etc.) that are defined in u1. If u2 has a foo subroutine that is not available to u1.
Now if u1 refers two more units u11 and u12 and u12 has a foo in it, then u1 can happily use it, refer to it.
My expectation that in the above set-up where both u2 and u12 have foo, the compiler tells the linker which foo to use (u2.foo in u2 and u12.foo in u1). However there are some special units (e.g. cmem, cthread, heaptrc) that are normally only referred to in the highest position (main program, top unit, or in case of the heaptrc only in the compiler options), still a lower level unit works differently if the unit is added even outside its normal scope. So, I assume in these cases the lower level unit call to "a" foo is changing at link time and suddenly refers to the top unit foo and not the foo that is directly seen by the unit already at compile time.
Is it so, or is there some compiler/linker magic behind these? How do they do this?
MarkMLl:
An alternative explanation- I'm not necessarily saying this applies in all cases- is that cmem etc. patch themselves into heap management at program startup: note that such things are generally accessed via a function-pointer variable.
MarkMLl
marcov:
No, there is no compiler/linker magic. Those kind of units set a global variable (typically a record with callbacks) that other parts of the RTL use.
If you don't add the unit, some defaults (in the unix specific case often empty) are used.
Heaptrc needs compiler support to also initialize before implicit units like objpas. Objpas is implicitely included when you use mode Delphi or objfpc (per mode or per parameter)
cdbc:
Hi
What the others said and then there's "aliasing", here's an example:
--- 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";}};} ---{ here we get the compiler to /export/ this function as publicly available }function PickLastDir(const aPath: string): string; public name 'BC_PICKLASTDIR'; implementation function PickLastDir(const aPath: string): string;var li: integer;begin if aPath = '' then exit(aPath); /// well duh! { user entered just a directory name, no path -> return it without 'pathdelim' } if pos(PathDelim,aPath) = 0 then Result:= aPath else begin { find the last 'pathdelim' in string & copy last part to result } li:= Length(aPath); if aPath[li] = PathDelim then dec(li); /// could end in a 'pathdelim', skip that while ((li > 0) and (aPath[li] <> PathDelim)) do dec(li); /// scan backwards { only 2 params = from idx and rest of string + replace 'pathdelim' with '' } if li > 0 then Result:= copy(aPath,li).Replace(PathDelim,'',[rfReplaceAll]) else Result:= aPath.Replace(PathDelim,'',[rfReplaceAll]); /// should get rid of the trailing one if present end;end;and in another unit we then alias the previous function by name, so that we can call it...:
--- 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";}};} ---{ utility functions, here we publicly export these functions, to be made available in other units, that can't /see/ us, for import :o) gotta love FPC \o/\รถ/\o/ }function Pch2Str(aPch: pchar): string; public name 'BC_PCH2STR';function Str2Pch(aStr: string): pchar; public name 'BC_STR2PCH';{ AND HERE WE IMPORT THE PUBLIC ALIASED FUNCTION }function PickLastDir(const aPath: string): string; external name 'BC_PICKLASTDIR';The RTL also makes use of aliasing, e.g.: 'InterlockIncrement()' in classes unit, amo.
Regards Benny
MarkMLl:
--- Quote from: marcov on December 02, 2024, 09:04:00 am ---No, there is no compiler/linker magic.
--- End quote ---
Except, I believe, that the compiler renames e.g. the unit to access debug line numbers.
--- 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";}};} ---(* Prior to around FPC 2.6.4 it was necessary to import LineInfo here. Later *)(* versions of the compiler implicitly import it, and are unhappy at an attempt *)(* to explicitly import it. *)(* *)(* This is complicated by the fact that at least some versions of the compiler *)(* apparently rewrite "LineInfo" here to "lnfodwrf" to track the format being *)(* used. *) uses StrUtils, Linux, Unix, BaseUnix, Errors {$ifdef USE_LINE_NUMBERS } , { LineInfo, } lnfodwrf {$endif }
That was derived from discussion on the ML.
MarkMLl
Navigation
[0] Message Index
[#] Next page