Recent

Author Topic: Call freepascal unit from C  (Read 6570 times)

Olam

  • New Member
  • *
  • Posts: 12
Re: Call freepascal unit from C
« Reply #15 on: June 10, 2022, 05:04:52 pm »
asm("name") is only needed for macOS to be able to call with "name" instead of "_name". C on mach-o prepends symbols with an underscore. so extern "C" void sym(); refers to a symbol named _sym(). Same for clang and gcc.

But that's the point: you shouldn't need that, because the compiler knows about the C prefix and should insert it itself. If it doesn't then either there is a bug or you do something wrong.

Ok, makes sense, that's what I would have expected, but adding "public name 'Func'" to a declaration makes a Symbol with the name "Func", not "_Func". Without public name 'Name' I'm left with the mangled name, not sure how to refer to that cleanly? So, bug? I would ofc prefer not to need the asm("")

But the LIBRARY export does _Func, unmangled, interesting.

Roland57

  • Hero Member
  • *****
  • Posts: 609
    • msegui.net
Re: Call freepascal unit from C
« Reply #16 on: June 10, 2022, 05:47:33 pm »
I have just found this interesting example in the German-speaking forum:
https://www.lazarusforum.de/viewtopic.php?f=9&t=13924

I tested the example under Windows with success. Now I am back to home, I will test under Linux.

Hi roland57, we don't see you much in FB these days.

Hi. It's true.  :)
My projects are on Codeberg.

Olam

  • New Member
  • *
  • Posts: 12
Re: Call freepascal unit from C
« Reply #17 on: June 10, 2022, 06:01:09 pm »
I have just found this interesting example in the German-speaking forum:
https://www.lazarusforum.de/viewtopic.php?f=9&t=13924


Didn't understand much of the text but I'm not sure 64 bit CPU is what makes the differences. Perhaps that's what was discussed.

Code: [Select]
public name{$IFDEF CPU64} 'fpc_add'{$ELSE} '_fpc_add'{$ENDIF};
« Last Edit: June 10, 2022, 07:07:38 pm by Olam »

Roland57

  • Hero Member
  • *****
  • Posts: 609
    • msegui.net
Re: Call freepascal unit from C
« Reply #18 on: June 10, 2022, 06:06:58 pm »
I tested corpsman example also under Linux. It works perfectly for me. I attach it here, with compilation scripts, in case someone would like to try it.
« Last Edit: June 10, 2022, 06:09:27 pm by Roland57 »
My projects are on Codeberg.

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: Call freepascal unit from C
« Reply #19 on: June 12, 2022, 07:52:43 pm »

My previous post loaded a dll at run time.
This loads a dll at compile time.
fp 3.2.2
gcc 12

replace.pas
Code: Pascal  [Select][+][-]
  1. library replace;
  2. uses
  3. sysutils;
  4.  
  5. function SAR(s:pchar;find:pchar;replace:pchar):pchar;
  6. begin
  7. exit(pchar(stringreplace(ansistring(s),ansistring(find),ansistring(replace),[rfReplaceAll])));
  8. end;
  9.  
  10. procedure show(s:pchar);
  11. var
  12. a:ansistring;
  13. begin
  14. a:=s;
  15. writeln(a);
  16. end;
  17.  
  18. procedure wait();
  19. begin
  20. readln;
  21. end;
  22.  
  23. exports
  24.  show,SAR,wait;
  25. end.
  26.  
  27.  
c test code
Code: Pascal  [Select][+][-]
  1.  
  2. #include<string.h>
  3.  
  4.   void     wait();
  5.   void     show(char*);  
  6.   char *   SAR(char*,char*,char*);
  7.   #define plenty 100
  8. int main(){
  9.   char string[]="This is a C string.";
  10.   char temp[plenty];
  11.   char * result;
  12.  
  13.    show(string);
  14.    result=SAR(string,"C","returned");
  15.    strcpy(temp, result);
  16.    show(temp);
  17.    result=SAR(temp,"returned","C language");
  18.    strcpy(temp, result);
  19.    show(temp);
  20.    result=SAR(temp,"string","string returned again");
  21.    strcpy(temp, result);
  22.    show(temp);
  23.    show("Press return to continue . . .");
  24.   wait();
  25. }
  26.  
  27.  
You should make sure your c code has access to the dll.
Best way is to put the c code and dll together.
Example
gcc.exe "path to somename.c and replace.dll\somename.c" -o "path to somename.c and replace.dll \somename.exe" -l replace  -L" path to somename.c and replace.dll" -static-libgcc
or
You can probably do this in your c ide/editor

Nobody has suggested a way to use variadic parameters in pascal (to fully use writeln in c), maybe it is not possible?


 



440bx

  • Hero Member
  • *****
  • Posts: 6532
Re: Call freepascal unit from C
« Reply #20 on: June 12, 2022, 08:33:55 pm »
Nobody has suggested a way to use variadic parameters in pascal (to fully use writeln in c), maybe it is not possible?
calling writeln _directly_ from C/C++ is not possible because there is a lot of "compiler magic" that goes into implementing a call to writeln.  Compiler magic that C/C++ are totally oblivious to (which is why the printf family of functions use a format string followed by parameters and, bad news follow if the parameters passed are not correctly matched to the format string spec.)

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Roland57

  • Hero Member
  • *****
  • Posts: 609
    • msegui.net
Re: Call freepascal unit from C
« Reply #21 on: June 12, 2022, 09:35:38 pm »
My previous post loaded a dll at run time.
This loads a dll at compile time.

I like your example. Compiles and runs fine here on Linux.

Code: Bash  [Select][+][-]
  1. fpc replace.pas
  2. gcc -L. -Wall -o test main.c -lreplace
  3. LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ && export LD_LIBRARY_PATH && ./test

I would have imagined that the keyword extern would be necessary in this line:
Code: C  [Select][+][-]
  1. char * SAR(char*,char*,char*);

I see that it is not.
« Last Edit: June 12, 2022, 09:39:10 pm by Roland57 »
My projects are on Codeberg.

Olam

  • New Member
  • *
  • Posts: 12
Re: Call freepascal unit from C
« Reply #22 on: June 13, 2022, 12:07:03 pm »
Quote
I would have imagined that the keyword extern would be necessary in this line:
Code: C  [Select][+][-]
  1. char * SAR(char*,char*,char*);

I see that it is not.

You need the extern "C" in C++ only, to tell the compiler to look for a symbol that is not mangled. try to nm name.o a file compiled with g++, clang++ or other C++ compilers to see mangled symbols. they contain parameters incl return type, this is how C++ overload resolution works. fpc uses similar trix for similar reasons.

Quote
Nobody has suggested a way to use variadic parameters in pascal (to fully use writeln in c), maybe it is not possible?
There is no writeln symbol in your library, "nm" it. I'm not familiar enough with pascal to se how it's done but I guess the compiler puts in a jump address to the appropriate fpc_xxxx functions.At least that's what it looks like debugging into writeln.


MarkMLl

  • Hero Member
  • *****
  • Posts: 8572
Re: Call freepascal unit from C
« Reply #23 on: June 13, 2022, 12:34:10 pm »
I'm not familiar enough with pascal to se how it's done but I guess the compiler puts in a jump address to the appropriate fpc_xxxx functions.At least that's what it looks like debugging into writeln.

Don't go there. Write(), WriteLn() and so on are backed by a whole lot of compiler magic, and you'd be dealing with both that and dynamically-managed Pascal-style strings.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Olam

  • New Member
  • *
  • Posts: 12
Re: Call freepascal unit from C
« Reply #24 on: June 13, 2022, 01:35:41 pm »
I'm not familiar enough with pascal to se how it's done but I guess the compiler puts in a jump address to the appropriate fpc_xxxx functions.At least that's what it looks like debugging into writeln.

Don't go there. Write(), WriteLn() and so on are backed by a whole lot of compiler magic, and you'd be dealing with both that and dynamically-managed Pascal-style strings.

MarkMLl

Hehe, that was kind of my point, but choosing not to call it magic. But indeed, unless you want to rewrite the compiler, you are better of making a wrapper, or why not
Code: C  [Select][+][-]
  1. #define writeln(...) std::cout << __VA_ARGS__ << '\n'
Bob's your uncle.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8572
Re: Call freepascal unit from C
« Reply #25 on: June 13, 2022, 02:19:40 pm »
Hehe, that was kind of my point, but choosing not to call it magic. But indeed, unless you want to rewrite the compiler, you are better of making a wrapper, or why not
Code: C  [Select][+][-]
  1. #define writeln(...) std::cout << __VA_ARGS__ << '\n'
Bob's your uncle.

For your next assignment, convert the WriteLn()-style :digits etc. notation as well :-)

Pascal was designed in an era where most languages built their I/O into the compiler. Some of the syntax diagrams make strong men weep.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 6396
  • Compiler Developer
Re: Call freepascal unit from C
« Reply #26 on: June 13, 2022, 02:31:21 pm »
However to create writeln as a variadic procedure, to accept different data types, seperated by commas, is not so trivial, in fact I can see no examples, references, or help about pascal variadic procedures.
Maybe somebody could help?

It is not supported to implement C-style variadic functions in FPC (you can call them however).

asm("name") is only needed for macOS to be able to call with "name" instead of "_name". C on mach-o prepends symbols with an underscore. so extern "C" void sym(); refers to a symbol named _sym(). Same for clang and gcc.

But that's the point: you shouldn't need that, because the compiler knows about the C prefix and should insert it itself. If it doesn't then either there is a bug or you do something wrong.

Ok, makes sense, that's what I would have expected, but adding "public name 'Func'" to a declaration makes a Symbol with the name "Func", not "_Func". Without public name 'Name' I'm left with the mangled name, not sure how to refer to that cleanly? So, bug? I would ofc prefer not to need the asm("")

With public name 'Func' you explicitly overwrite what is exported. That's why I said you shouldn't add that. The exports-clause then exports both the mangled symbol as well as a C-style one (at least that's how it's supposed to work).

Thaddy

  • Hero Member
  • *****
  • Posts: 19268
  • Glad to be alive.
Re: Call freepascal unit from C
« Reply #27 on: June 13, 2022, 02:37:56 pm »
Note in FPC - but NOT in Delphi- Varargs are equivalent to an array of const.
See the manual for an example: https://www.freepascal.org/docs-html/current/ref/refsu97.html
« Last Edit: June 13, 2022, 02:39:51 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6396
  • Compiler Developer
Re: Call freepascal unit from C
« Reply #28 on: June 13, 2022, 02:40:20 pm »
Note in FPC - but NOT in Delphi, Varargs are equivalent to an array of const.
See: https://www.freepascal.org/docs-html/current/ref/refsu97.html

That is only for calling an external function. You can't implement a C varargs function in FPC using array of const.

 

TinyPortal © 2005-2018