obj file linking (external function) lazarus / 62-General ---------------------------------------------------------------------- DevilDevil · 2020-03-25 12:11 I am developing a Tiny.Rtti library that should work in Delphi and FreePascal. Low-level code (including assembler) is written in C and compiled by the Clang cross-compiler into object files. The Delphi compiler easily links these files, but the FPC produces strange errors! Let's take a simple example (attached to the post). Code: C++  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i // test.cint external_func(); int add(int x, int y, int z){    return (x + y + z + external_func());       } Code: [Select]:: compile.bat clang -target x86_64-windows-gnu -c -O3 test.c -o"test.o" pause Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; {$APPTYPE CONSOLE}{$L test.o} function external_func: Integer;begin  Result := 4;end; function add(X, Y, Z: Integer): Integer; external name 'add'; var  R: Integer;begin  R := add(1, 2, 3);  Writeln('1 + 2 + 3 + 4 = ', R);  Readln;end.    This design works great in Delphi, but it doesn’t link in FreePascal: QuoteProject1.dpr(6,10) Hint: Local proc "external_func" is not used Project1.dpr(19,1) Error: Undefined symbol: external_func Tell me, please, how to fix this? ---------------------------------------------------------------------- avk · 2020-03-25 13:05 Try this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1;{$ifndef fpc}  {$APPTYPE CONSOLE}{$else}  {$mode delphi}{$endif}{$L test.o}uses  Rtti; function external_func: Integer; public name 'external_func';begin  Result := 4;end; function add(X, Y, Z: Integer): Integer; external name 'add'; var  R: Integer;begin  R := add(1, 2, 3);  Writeln('1 + 2 + 3 + 4 = ', R);  Readln;end. ---------------------------------------------------------------------- DevilDevil · 2020-03-25 13:18 public name 'external_func'; helped! Thank you ---------------------------------------------------------------------- DevilDevil · 2020-03-25 14:12 Damn! The object file is linked on Windows, but not on Linux. Quote:: compile.bat clang -target x86_64-linux-gnu -c -O3 test.c -o"test.o" pause This works in Delphi, but it displays the following message in FreePascal: QuoteProject1.dpr(19,1) Error: Illegal COFF Magic while reading test.o Object file (for Linux x86-64) attached ---------------------------------------------------------------------- avk · 2020-03-25 16:35 Cannot reproduce your error. On Linux x86_64, everything works as expected. ---------------------------------------------------------------------- DevilDevil · 2020-03-25 19:00 Quote from: avk on March 25, 2020, 05:35:55 pmCannot reproduce your error. On Linux x86_64, everything works as expected. It looks like you are using an unofficial FPC release. I am using 3.0.4 ---------------------------------------------------------------------- marcov · 2020-03-25 19:55 Quote from: DevilDevil on March 25, 2020, 08:00:32 pmQuote from: avk on March 25, 2020, 05:35:55 pmCannot reproduce your error. On Linux x86_64, everything works as expected. It looks like you are using an unofficial FPC release. I am using 3.0.4 I doubt even 3.0.4 generates COFF files on *nix. Usually that is ELF.  Make sure your target is linux, not windows ---------------------------------------------------------------------- DevilDevil · 2020-03-25 20:16 avk, marcov, I apologize. Looks like Tiny.Rtti supports FPC: https://github.com/d-mozulyov/Tiny.Rtti ---------------------------------------------------------------------- DevilDevil · 2020-05-10 23:33 Hello everyone It is necessary to publish a variable, such code compiles normally: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  MY_VARIABLE: Integer public name 'MY_VARIABLE'; But if I set the value of a variable, I can’t publish it anymore. What should be the syntax? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  MY_VARIABLE: Integer = 0 public name 'MY_VARIABLE'; ---------------------------------------------------------------------- jamie · 2020-05-11 00:56 I am going to take a guess to say it don't support that construct.. try putting = 0 at the end. Actually, can't you initiate it else where? maybe what you are looking for is a writeable constant ? Const MYVariable:Type=SomeValue; Try putting the PUBLIC/Export on a different line;; ---------------------------------------------------------------------- PascalDragon · 2020-05-11 07:06 Quote from: DevilDevil on May 11, 2020, 01:33:50 amHello everyone It is necessary to publish a variable, such code compiles normally: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  MY_VARIABLE: Integer public name 'MY_VARIABLE'; But if I set the value of a variable, I can’t publish it anymore. What should be the syntax? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  MY_VARIABLE: Integer = 0 public name 'MY_VARIABLE'; Add a semicolon at the right location: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  MY_VARIABLE: Integer = 0; { !!!! } public name 'MY_VARIABLE'; ---------------------------------------------------------------------- DevilDevil · 2020-05-11 07:56 PascalDragon, QuoteFatal: Syntax error, ":" expected but "identifier NAME" found ---------------------------------------------------------------------- ASerge · 2020-05-11 08:27 Quote from: DevilDevil on May 11, 2020, 09:56:36 amFatal: Syntax error, ":" expected but "identifier NAME" found We need the full code, because this project compiles without any problems:Code: [Select]var   MY_VARIABLE: Integer = 0; public name 'MY_VARIABLE'; begin end. ---------------------------------------------------------------------- Thaddy · 2020-05-11 08:51 You can not use the same C obj file on linux and windows. You need to compile the C code for Windows AND you need to compile the same C code for Linux. It is COFF vs ELF. E.g. use msvc for windows and GNU C for linux. Once you do that, with the addition of avk and ASerge remarks your code works. Cross platform AND bitness. Tested. I used cdecl for Linux and stdcall for windows, btw. Once you follow that, it also works on e.g. a Raspberry Pi. Also note that FPC generates about the same assembler as the C compilers with your simple example, so why use C? (I always find it really funny that people think the C code must be more efficient, that it not always true) Note I suspect you did not test Delphi 64 bit Linux: that would give you the same problems. Note clang, when properly configured, should not have caused any problems on both platforms, but as explained, I did not use it for my test, just msvc and GNU C, because that is what I use most. For completeness I tested with FPC 3.3.1-r45267 and win32, 64 and linux Intel 64 and a Rasbian (32bit armhf-linux) ---------------------------------------------------------------------- DevilDevil · 2020-05-11 09:11 ASerge, {$MODE DELPHI}  leads to an error ---------------------------------------------------------------------- Thaddy · 2020-05-11 12:23 On which platform? Again with half of the information we can't help you. And, btw, your code works if you follow our combined advice. I tested that... You did not even try, as ASerge will probably confirm. We can't help you if you do not follow the steps we tested. I know ASerge and avk also test what we have.... Next time I will add a grumpy.  And this thread gives you well over a combined total of maybe well over a hundred years of  experience in programming and proper advice. ---------------------------------------------------------------------- DevilDevil · 2020-05-11 12:43 Thaddy, This code does not compile Windows 64 FPC 3.0.4 version Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program test; {$MODE DELPHI} //! var  MY_VARIABLE: Integer = 0; public name 'MY_VARIABLE';beginend. ---------------------------------------------------------------------- Thaddy · 2020-05-11 13:01 because you did not specify where the linker can find it.... silly. external 'whatever library' name "whatever and matching the exactname" What you do works on some platforms, but not on others. Plz be very specific. Half information is guess work. I tested your code with the suggested modifications and platform specifics and it works. Note some windows  specific defines of course does not work on linux. ETA Wait a minute, I will show you. See https://wiki.freepascal.org/Public ---------------------------------------------------------------------- DevilDevil · 2020-05-11 13:17 Thaddy, How to declare a variable that will be visible inside object files on Windows, Linux and other platforms? The above example does not compile ---------------------------------------------------------------------- ASerge · 2020-05-11 15:33 Quote from: DevilDevil on May 11, 2020, 11:11:21 am{$MODE DELPHI}  leads to an error Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$MODE DELPHI}{$MODESWITCH CVAR}var  MY_VARIABLE: Integer = 0; public name 'MY_VARIABLE';beginend. ---------------------------------------------------------------------- Thaddy · 2020-05-11 15:39 Quote from: DevilDevil on May 11, 2020, 03:17:16 pmThaddy, How to declare a variable that will be visible inside object files on Windows, Linux and other platforms? The above example does not compile Look at ASerge's answer. Note that afaik this does not work for the real Delphi proper at leats not older versions, but it works in FreePascal in any mode. Delphi can not export variables, maybe now it does in the more modern 10.3.3. Do you want my project, if necessary? I can attach it. Did not touch - much - code, just choice of compilers. I am sure my tests, avk and ASerge also have working test programs. ---------------------------------------------------------------------- DevilDevil · 2020-05-11 15:48 ASerge, Thanks. Compiles. How does the option affect the compiler? ---------------------------------------------------------------------- DevilDevil · 2020-05-11 15:51 Thaddy, No thanks. I successfully link obj files to Delphi and FPC projects. ---------------------------------------------------------------------- PascalDragon · 2020-05-12 07:06 Quote from: Thaddy on May 11, 2020, 03:01:12 pmbecause you did not specify where the linker can find it.... silly. external 'whatever library' name "whatever and matching the exactname" DevilDevil had said multiple times that they had a syntax error. This is way before the linker is even remotely involved. Read -> Think -> Post. But thanks to ASerge it is solved anyway, at least as long as DevilDevil doesn't want to use the source in Delphi as well. ---------------------------------------------------------------------- DevilDevil · 2020-05-12 08:52 PascalDragon Thank you guys With Delphi there are practically no problems in terms of linking. Standard Win32/Win64 pick up variables without any directives. LLVM compilers need to specify a variable or function in the exports section. But variables indicating the value cannot be connected yet, though By the way. I still do not understand what CVAR mode is, and why does it allow you to compile the above construction? ---------------------------------------------------------------------- trev · 2020-05-12 12:41 Free Pascal Programmer’s Guide: cvar ---------------------------------------------------------------------- ASerge · 2020-05-12 13:57 Quote from: DevilDevil on May 11, 2020, 05:48:04 pmThanks. Compiles. How does the option affect the compiler? Since Delphi does not have such features as external variable names (public) the compiler (in mode DELPHI) does not search for them. The option CVAR force it to do this. ---------------------------------------------------------------------- DevilDevil · 2020-05-12 14:15 ASerge, In the standard Delphi compiler (Win32/Win64), you must declare a variable declared in the obj file so that the file is linked. Does CVAR mode work in the same way or obliges to specify public/cvar directives? ---------------------------------------------------------------------- PascalDragon · 2020-05-13 07:36 $modeswitch cvar simply enables the parsing of the cvar as well as the public name '…' directive which is disabled in mode Delphi by default, cause Delphi does not support that syntax. ---------------------------------------------------------------------- DevilDevil · 2020-05-13 07:38 PascalDragon, Thank you!