Recent

Author Topic: FPC 3.2.2 - how to fix export error ?  (Read 1969 times)

paule32

  • Hero Member
  • *****
  • Posts: 645
  • One in all. But, not all in one.
FPC 3.2.2 - how to fix export error ?
« on: May 08, 2025, 09:58:12 am »
hello,

I have the following Code, and get this Compiler-Messages:

Code: Bash  [Select][+][-]
  1. fpc -dDLLEXPORT -dLANGDEU -n -B -Os -CD Locales.pas
  2. Locales.pas(30,10) Error: The symbol cannot be exported from a library
  3. Locales.pas(27) Fatal: There were 1 errors compiling module, stopping
  4. Fatal: Compilation aborted
  5. Error: C:\fpcupdeluxe\fpc\bin\x86_64-win64\ppcx64.exe returned an error exitcode

Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2. unit Locales;
  3.  
  4. interface
  5. uses global;
  6.  
  7. // english
  8. {$ifdef DLLEXPORT}
  9.   {$ifdef LANGENU}
  10.   const
  11.     sHello = 'Hello World';
  12.   {$endif LANGENU}
  13.  
  14.   // german
  15.   {$ifdef LANGDEU}
  16.   const
  17.     sHello = 'Hallo Welt';
  18.   {$endif LANGDEU}
  19. {$endif DLLEXPORT}
  20.  
  21. {$ifdef DLLIMPORT}
  22. var
  23.   sHello: string; external RTLDLL;
  24. {$endif DLLIMPORT}
  25.  
  26. implementation
  27.  
  28. {$ifdef DLLEXPORT}
  29. exports
  30.   sHello name 'sHello'
  31.   ;
  32. {$endif DLLEXPORT}
  33.  
  34. end.

My Command Line is as follows:

Code: Bash  [Select][+][-]
  1. fpc -dDLLEXPORT -dLANGDEU -n -B -Os -CD Locales.pas

How can I fix that ?
MS-IIS - Internet Information Server, Apache, PHP/HTML/CSS, MinGW-32/64 MSys2 GNU C/C++ 13 (-stdc++20), FPC 3.2.2
A Friend in need, is a Friend indeed.

Khrys

  • Sr. Member
  • ****
  • Posts: 391
Re: FPC 3.2.2 - how to fix export error ?
« Reply #1 on: May 08, 2025, 10:15:21 am »
You need to use typed constants instead of ordinary constants. The former are essentially static variables, while the latter are more like macros (e.g. they don't have an address).

Code: Pascal  [Select][+][-]
  1. const
  2.   sHello: String = 'Hello World';

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: FPC 3.2.2 - how to fix export error ?
« Reply #2 on: May 08, 2025, 11:59:53 am »
In libraries it is often better to use a pchar:
Code: Pascal  [Select][+][-]
  1. library helloworld;
  2. const
  3.   hello:pchar = 'hello, world';export;
  4. exports
  5.   hello;
  6. end.
Demo:
Code: Pascal  [Select][+][-]
  1. program helloworlddemo;
  2. {$mode objfpc}{$H+}
  3. var
  4.   hello:pchar external 'helloworld.dll' name 'hello';
  5. begin
  6.   writeln(hello);
  7. end.
This way it also works with other programming languages.

But in your case you may want to have a look at resourcestring in the manuals.
Also: compile with the -WR option added. (relocatable code)

It also works on Linux: change dll to so. and prefix with lib exclude -WR.

 
« Last Edit: May 08, 2025, 12:38:57 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

paule32

  • Hero Member
  • *****
  • Posts: 645
  • One in all. But, not all in one.
Re: FPC 3.2.2 - how to fix export error ?
« Reply #3 on: May 08, 2025, 12:55:31 pm »
Thank you @all replyer.

The magic was: {$mode objfpc}{H+}
Because I used: {$mode delphi}

with the first one, I get working this Script with a little bit payload.
I don't need "resourcestring" and maintain .rc File.

I have to explicit write AnsiString, because the fpcobj mode seems to have ShortString by default.
And when I use variable AnsiString's per:
var
  sString: AnsiString = 'foo'; export;

The export does work.
So, all is out of the box by one Hand:

Code: Pascal  [Select][+][-]
  1. unit Locales;
  2. {$mode objfpc}{$H+}
  3.  
  4. interface
  5. uses global;
  6.  
  7. // english
  8. {$ifdef DLLEXPORT}
  9.   {$ifdef LANGENU}
  10.   var
  11.     sInformation: AnsiString = 'Informations'; export;
  12.     sWarning: AnsiString = 'Warning'; export;
  13.     sError: AnsiString = 'Error'; export;
  14.     sHello: AnsiString = 'Hello World'; export;
  15.   {$endif LANGENU}
  16.  
  17.   // german
  18.   {$ifdef LANGDEU}
  19.   var
  20.     sInformation: AnsiString = 'Information'; export;
  21.     sError: AnsiString = 'Fehler'; export;
  22.     sHello: AnsiString = 'Hallo Welt'; export;
  23.   {$endif LANGDEU}
  24. {$endif DLLEXPORT}
  25.  
  26. {$ifdef DLLIMPORT}
  27. var
  28.   sInformation: AnsiString; external RTLDLL;
  29.   sWarning: AnsiString; external RTLDLL;
  30.   sError: AnsiString; external RTLDLL;
  31.   sHello: AnsiString; external RTLDLL;
  32. {$endif DLLIMPORT}
  33.  
  34. implementation
  35.  
  36. {$ifdef DLLEXPORTss}
  37. exports
  38.   sInformation name 'sInformation',
  39.   sWarning     name 'sWarning',
  40.   sError       name 'sError',
  41.   sHello       name 'sHello'
  42.   ;
  43. {$endif DLLEXPORT}
  44.  
  45. end.
  46.  

sometimes I thinking I do voodoo programming ... :-\
« Last Edit: May 08, 2025, 01:08:20 pm by paule32 »
MS-IIS - Internet Information Server, Apache, PHP/HTML/CSS, MinGW-32/64 MSys2 GNU C/C++ 13 (-stdc++20), FPC 3.2.2
A Friend in need, is a Friend indeed.

Zvoni

  • Hero Member
  • *****
  • Posts: 3246
Re: FPC 3.2.2 - how to fix export error ?
« Reply #4 on: May 08, 2025, 01:31:19 pm »
And i repeat what Thaddy wrote: Use PChar

I seem to remember there are memory-issues, when trying to pass Strings from/to a Library/DLL
Something to do with needing a "fpcmemdll.dll" on Windows or some such
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

paule32

  • Hero Member
  • *****
  • Posts: 645
  • One in all. But, not all in one.
Re: FPC 3.2.2 - how to fix export error ?
« Reply #5 on: May 08, 2025, 04:31:33 pm »
I was thinking PChar is null-terminated, so you don't know how long the string is if you not even iterate it before to count the non-null byte chars.
And on AnsiString, you have the referenced Length at the begining of the string.

Simplest example is ShortString [len][string]
where len can be not over 255 Bytes
because the Byte range 0..255 Bytes.

Pchar: [Array(char's)][0-byte]   same to:   PWchar: [Array(0+char)][00-byte]

For me it sounds better AnsiString - but this my preferences - I will always learn new...
MS-IIS - Internet Information Server, Apache, PHP/HTML/CSS, MinGW-32/64 MSys2 GNU C/C++ 13 (-stdc++20), FPC 3.2.2
A Friend in need, is a Friend indeed.

Fred vS

  • Hero Member
  • *****
  • Posts: 3778
    • StrumPract is the musicians best friend
Re: FPC 3.2.2 - how to fix export error ?
« Reply #6 on: May 08, 2025, 05:02:35 pm »
Hello.

Mainly for library better use cmem  as memory manager.

So, in uses section, add as first (or only) unit:

Code: Pascal  [Select][+][-]
  1. uses
  2. cmem, ... ;
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: FPC 3.2.2 - how to fix export error ?
« Reply #7 on: May 08, 2025, 05:40:08 pm »
I was thinking PChar is null-terminated, so you don't know how long the string is if you not even iterate it before to count the non-null byte chars.
And on AnsiString, you have the referenced Length at the begining of the string.
That is absolute nonsense. See my example. You do not need to know the length because the PChar is external.
When you assign it to a variable it makes a pointer copy, not a deep copy.
But you can make a deep copy and make it a Pascal string like so:
Code: Pascal  [Select][+][-]
  1. var s:string;
  2. begin
  3.  setstring(s,externalpchar,strlen(externalpchar));
In that case you need strlen indeed, but not if you simply use Pchars.
« Last Edit: May 08, 2025, 06:15:54 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: FPC 3.2.2 - how to fix export error ?
« Reply #8 on: May 08, 2025, 06:25:43 pm »
Mainly for library better use cmem  as memory manager.

So, in uses section, add as first (or only) unit:

Code: Pascal  [Select][+][-]
  1. uses
  2. cmem, ... ;
In this case absolutely not necessary, because the pchars are hard-coded in the binary and do not use any memory at all.
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Fred vS

  • Hero Member
  • *****
  • Posts: 3778
    • StrumPract is the musicians best friend
Re: FPC 3.2.2 - how to fix export error ?
« Reply #9 on: May 08, 2025, 06:29:52 pm »
Mainly for library better use cmem  as memory manager.

So, in uses section, add as first (or only) unit:

Code: Pascal  [Select][+][-]
  1. uses
  2. cmem, ... ;
In this case absolutely not necessary, because the pchars are hard-coded in the binary and do not use any memory at all.

Yes, but maybe its complete library doesn't just export a hello to the world. :-X
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

paule32

  • Hero Member
  • *****
  • Posts: 645
  • One in all. But, not all in one.
Re: FPC 3.2.2 - how to fix export error ?
« Reply #10 on: May 08, 2025, 07:01:42 pm »
Yes, but maybe its complete library doesn't just export a hello to the world. :-X

indeed.
It will become a complete library - but what is complete now a days ?  %)

I can not show the original Code because I am contracted by @fibodev aka @fibonacci.
You can ask him, if you can take a Look - from me, I can not give the green light...
MS-IIS - Internet Information Server, Apache, PHP/HTML/CSS, MinGW-32/64 MSys2 GNU C/C++ 13 (-stdc++20), FPC 3.2.2
A Friend in need, is a Friend indeed.

Fibonacci

  • Hero Member
  • *****
  • Posts: 788
  • Internal Error Hunter
Re: FPC 3.2.2 - how to fix export error ?
« Reply #11 on: May 08, 2025, 07:17:12 pm »
Yes, confirmed. Strictly classified, I cant say anything more. Shhhh... :-X

PascalDragon

  • Hero Member
  • *****
  • Posts: 6315
  • Compiler Developer
Re: FPC 3.2.2 - how to fix export error ?
« Reply #12 on: May 08, 2025, 09:14:25 pm »
For me it sounds better AnsiString - but this my preferences - I will always learn new...

It does not matter what your preference is. If library boundaries are involved special care needs to be taken for both AnsiString and UnicodeString so that both the library and the main application use the same memory manager otherwise this will end in problems. The same is also true for any other allocations including PChar if they're allocated in one binary and released in the other, but there you have manual allocations/deallocations in comparison to the managed string types.

paule32

  • Hero Member
  • *****
  • Posts: 645
  • One in all. But, not all in one.
Re: FPC 3.2.2 - how to fix export error ?
« Reply #13 on: May 09, 2025, 08:27:54 am »
Currently, I use fibonacci's private memory manager.
The main work of me is, to outsource used Pascal Code to DLL File so, EXE File will become smaller
MS-IIS - Internet Information Server, Apache, PHP/HTML/CSS, MinGW-32/64 MSys2 GNU C/C++ 13 (-stdc++20), FPC 3.2.2
A Friend in need, is a Friend indeed.

paule32

  • Hero Member
  • *****
  • Posts: 645
  • One in all. But, not all in one.
Re: FPC 3.2.2 - how to fix export error ?
« Reply #14 on: May 09, 2025, 08:47:55 am »
I have written a Python Script, that dump the Symbols of .ppu, and .o Files.
Feel free to use it.
Any proof is welcome...
It used Qt5 as GUI:

Code: Pascal  [Select][+][-]
  1. # ---------------------------------------------------------------------------------------
  2. # Copyright(c) 2025 @paule32 & @fibodev
  3. # ---------------------------------------------------------------------------------------
  4. import sys
  5. import os
  6. import subprocess
  7. import re
  8. from PyQt5.QtWidgets import (
  9.     QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QComboBox,
  10.     QPushButton, QFileDialog, QPlainTextEdit, QLabel, QLineEdit, QSplitter
  11. )
  12. from PyQt5.QtCore import Qt
  13.  
  14. class PascalSymbolBrowser(QWidget):
  15.     def __init__(self):
  16.         super().__init__()
  17.         self.setWindowTitle("Pascal Symbol Browser")
  18.         self.resize(1000, 750)
  19.  
  20.         # Layouts
  21.         main_layout = QVBoxLayout()
  22.         control_layout = QHBoxLayout()
  23.         bottom_layout = QVBoxLayout()
  24.         button_layout = QHBoxLayout()
  25.  
  26.         # Combobox für .ppu-Dateien und Verzeichniswahl
  27.         self.combo_ppu = QComboBox()
  28.         self.combo_ppu.currentIndexChanged.connect(self.load_symbols)
  29.         self.btn_choose_dir = QPushButton("Select Directory")
  30.         self.btn_choose_dir.clicked.connect(self.choose_directory)
  31.         control_layout.addWidget(QLabel(".ppu File:"))
  32.         control_layout.addWidget(self.combo_ppu)
  33.         control_layout.addWidget(self.btn_choose_dir)
  34.  
  35.         # Listboxen mit Labels
  36.         self.label_ppu = QLabel(".ppu Symbols")
  37.         self.list_ppu = QListWidget()
  38.         self.list_ppu.itemClicked.connect(self.generate_code_for_selection)
  39.  
  40.         self.label_o = QLabel(".o Symbols")
  41.         self.list_o = QListWidget()
  42.         self.list_o.itemClicked.connect(self.generate_code_for_selection)
  43.  
  44.         list_layout_left = QVBoxLayout()
  45.         list_layout_left.setContentsMargins(2, 2, 2, 2)
  46.         list_layout_left.addWidget(self.label_ppu)
  47.         list_layout_left.addWidget(self.list_ppu)
  48.         list_container_left = QWidget()
  49.         list_container_left.setLayout(list_layout_left)
  50.  
  51.         list_layout_right = QVBoxLayout()
  52.         list_layout_right.setContentsMargins(2, 2, 2, 2)
  53.         list_layout_right.addWidget(self.label_o)
  54.         list_layout_right.addWidget(self.list_o)
  55.         list_container_right = QWidget()
  56.         list_container_right.setLayout(list_layout_right)
  57.  
  58.         list_splitter = QSplitter(Qt.Horizontal)
  59.         list_splitter.addWidget(list_container_left)
  60.         list_splitter.addWidget(list_container_right)
  61.  
  62.         # Zwei Editoren mit Labels unter den Listboxen
  63.         self.label_pascal = QLabel("Pascal Code")
  64.         self.editor_pascal = QPlainTextEdit()
  65.         editor_layout_left = QVBoxLayout()
  66.         editor_layout_left.setContentsMargins(2, 2, 2, 2)
  67.         editor_layout_left.addWidget(self.label_pascal)
  68.         editor_layout_left.addWidget(self.editor_pascal)
  69.         editor_container_left = QWidget()
  70.         editor_container_left.setLayout(editor_layout_left)
  71.  
  72.         self.label_asm = QLabel("Assembler Code")
  73.         self.editor_asm = QPlainTextEdit()
  74.         editor_layout_right = QVBoxLayout()
  75.         editor_layout_right.setContentsMargins(2, 2, 2, 2)
  76.         editor_layout_right.addWidget(self.label_asm)
  77.         editor_layout_right.addWidget(self.editor_asm)
  78.         editor_container_right = QWidget()
  79.         editor_container_right.setLayout(editor_layout_right)
  80.  
  81.         editor_splitter = QSplitter(Qt.Horizontal)
  82.         editor_splitter.addWidget(editor_container_left)
  83.         editor_splitter.addWidget(editor_container_right)
  84.  
  85.         # Horizontaler Splitter über Listboxen und Editoren
  86.         vertical_splitter = QSplitter(Qt.Vertical)
  87.         vertical_splitter.addWidget(list_splitter)
  88.         vertical_splitter.addWidget(editor_splitter)
  89.        
  90.         self.label_pascal_export_import = QLabel("Pascal Export, Import:")
  91.         self.editor_pascal_left = QPlainTextEdit()
  92.         editor_pascal_eximp_layout = QVBoxLayout()
  93.         editor_pascal_eximp_layout.setContentsMargins(2, 2, 2, 2)
  94.         editor_pascal_eximp_layout.addWidget(self.label_pascal_export_import)
  95.         editor_pascal_eximp_layout.addWidget(self.editor_pascal_left)
  96.         editor_pascal_container_left = QWidget()
  97.         editor_pascal_container_left.setLayout(editor_pascal_eximp_layout)
  98.        
  99.         editor_splitter_pascal = QSplitter(Qt.Horizontal)
  100.         editor_splitter_pascal.addWidget(editor_pascal_container_left)
  101.        
  102.         # Eingabezeile und Speichern-Button für ASM
  103.         self.asm_save_line = QLineEdit()
  104.         self.btn_save_asm = QPushButton("Assembler speichern unter")
  105.         self.btn_save_asm.clicked.connect(self.save_asm_code)
  106.         extra_layout = QHBoxLayout()
  107.         extra_layout.addWidget(self.asm_save_line)
  108.         extra_layout.addWidget(self.btn_save_asm)
  109.  
  110.         # Buttons unten
  111.         self.btn_load = QPushButton("Reset")
  112.         self.btn_load.clicked.connect(self.load_symbols)
  113.         self.btn_save = QPushButton("Pascal speichern unter")
  114.         self.btn_save.clicked.connect(self.save_code)
  115.         button_layout.addWidget(self.btn_load)
  116.         button_layout.addWidget(self.btn_save)
  117.  
  118.         # Layout zusammensetzen
  119.         main_layout.addLayout(control_layout)
  120.         main_layout.addWidget(vertical_splitter)
  121.         main_layout.addWidget(editor_splitter_pascal)
  122.        
  123.         main_layout.addLayout(extra_layout)
  124.         bottom_layout.addLayout(button_layout)
  125.         main_layout.addLayout(bottom_layout)
  126.         self.setLayout(main_layout)
  127.  
  128.         # Initiales Verzeichnis
  129.         self.current_dir = os.getcwd()
  130.         self.update_combo()
  131.  
  132.         # Aktuelle Zuordnung
  133.         self.mangled_names = []
  134.         self.o_symbols = []
  135.  
  136.     def choose_directory(self):
  137.         dir_ = QFileDialog.getExistingDirectory(self, "Verzeichnis wählen", self.current_dir)
  138.         if dir_:
  139.             self.current_dir = dir_
  140.             self.update_combo()
  141.  
  142.     def update_combo(self):
  143.         self.combo_ppu.clear()
  144.         files = [f for f in os.listdir(self.current_dir) if f.endswith('.ppu')]
  145.         self.combo_ppu.addItems(files)
  146.         if files:
  147.             self.load_symbols()
  148.             self.generate_code_for_selection()
  149.             self.generate_pascal_code()
  150.  
  151.     def load_symbols(self):
  152.         self.list_ppu.clear()
  153.         self.list_o.clear()
  154.         self.editor_pascal.clear()
  155.         self.editor_asm.clear()
  156.         selected_file = self.combo_ppu.currentText()
  157.         if not selected_file:
  158.             return
  159.  
  160.         ppu_path = os.path.join(self.current_dir, selected_file)
  161.  
  162.         # O-Datei suchen (gleicher Name wie .ppu, aber .o)
  163.         o_file = os.path.splitext(selected_file)[0] + '.o'
  164.         o_path = os.path.join(self.current_dir, o_file)
  165.         self.o_symbols = []
  166.  
  167.         if os.path.exists(o_path):
  168.             try:
  169.                 seen = set()
  170.                 result = subprocess.run(["nm", "-g", o_path], capture_output=True, text=True)
  171.                 for line in result.stdout.splitlines():
  172.                     match = re.search(r'([_A-Z]+\$[\w\$]*)', line)
  173.                     if match:
  174.                         symbol = match.group(1)
  175.                         if symbol not in seen:
  176.                             seen.add(symbol)
  177.                             self.list_o.addItem(symbol)
  178.                             self.o_symbols.append(symbol)
  179.             except Exception as e:
  180.                 self.list_o.addItem(f"Fehler: {e}")
  181.  
  182.         # PPU Symbole (via ppudump)
  183.         self.mangled_names = []
  184.         seen = set()
  185.         try:
  186.             output = subprocess.check_output(['ppudump', ppu_path], text=True)
  187.             for line in output.splitlines():
  188.                 if 'Alias names :' in line:
  189.                     parts = line.split(':', 1)[1].strip().split(',')
  190.                     for name in parts:
  191.                         name = name.strip().replace('$', '')
  192.                         if name and name not in seen:
  193.                             seen.add(name)
  194.                             self.list_ppu.addItem(name)
  195.                             self.mangled_names.append(name)
  196.                 elif 'Mangled name :' in line:
  197.                     name = line.split(':', 1)[1].strip().replace('$', '')
  198.                     if name and name not in seen:
  199.                         seen.add(name)
  200.                         self.list_ppu.addItem(name)
  201.                         self.mangled_names.append(name)
  202.                 elif 'Procedure symbol' in line and '$' not in line:
  203.                     symbol = line.split('symbol', 1)[1].strip().replace('$', '')
  204.                     if symbol and symbol not in seen:
  205.                         seen.add(symbol)
  206.                         self.list_ppu.addItem(symbol)
  207.                         self.mangled_names.append(symbol)
  208.         except Exception as e:
  209.             self.list_ppu.addItem(f"Error: {e}")
  210.  
  211.         self.generate_asm_code()
  212.         self.generate_pascal_exports()
  213.         self.generate_pascal_code()
  214.  
  215.     def generate_asm_code(self):
  216.         asm_lines = []
  217.         for name, symbol in zip(self.mangled_names, self.o_symbols):
  218.             asm_lines.append(f"global {name}")
  219.             asm_lines.append(f"{name}:")
  220.             asm_lines.append(f"    call {symbol}")
  221.             asm_lines.append(f"    ret")
  222.             asm_lines.append("")
  223.         self.editor_asm.setPlainText("\n".join(asm_lines))
  224.  
  225.     def generate_pascal_exports(self):
  226.         export_lines = ["library wrapperlib;", "", "exports"]
  227.         for name, symbol in zip(self.mangled_names, self.o_symbols):
  228.             export_lines.append(f"  {name} name '{symbol}',")
  229.         if len(export_lines) > 2:
  230.             export_lines[-1] = export_lines[-1].rstrip(',') + ';'
  231.         export_lines.append("")
  232.         export_lines.append("begin")
  233.         export_lines.append("end.")
  234.         self.editor_pascal.setPlainText("\n".join(export_lines))
  235.  
  236.     def generate_pascal_code(self):
  237.         pascal_code = (""
  238.         + "unit wrapper;\n"
  239.         + "interface\n" )
  240.         for i in range(self.list_ppu.count()):
  241.             item = self.list_ppu.item(i)
  242.             name = item.text()
  243.             pascal_code += (""
  244.             + "{$ifdef DLLEXPORT}\n"
  245.             + "procedure " + name + "; stdcall export\n"
  246.             + "{$endif DLLEXPORT}\n"
  247.             + "{$ifdef DLLIMPORT}\n"
  248.             + "procedure " + name + "; stdcall external RTLDLL;\n"
  249.             + "{$endif DLLIMPORT}\n\n"
  250.             )
  251.         pascal_code += (""
  252.         + "implementation\n"
  253.         + "end.")
  254.         self.editor_pascal_left.setPlainText(pascal_code);
  255.  
  256.     def generate_code_for_selection(self):
  257.         current_mangled = self.list_ppu.currentItem()
  258.         current_symbol = self.list_o.currentItem()
  259.        
  260.         if current_mangled and current_symbol:
  261.             name = current_mangled.text()
  262.             symbol = current_symbol.text()
  263.            
  264.             code = f"global {name}\n{name}:\n    call {symbol}\n    ret"
  265.             self.editor_asm.setPlainText(code)
  266.             self.editor_pascal.setPlainText(f"exports {name} name '{symbol}';")
  267.  
  268.     def save_code(self):
  269.         file_path, _ = QFileDialog.getSaveFileName(self, "Pascal-Datei speichern", self.current_dir, "*.pas")
  270.         if file_path:
  271.             if not file_path.endswith(".pas"):
  272.                 file_path += ".pas"
  273.             with open(file_path, 'w', encoding='utf-8') as f:
  274.                 f.write(self.editor_pascal.toPlainText())
  275.  
  276.     def save_asm_code(self):
  277.         file_path, _ = QFileDialog.getSaveFileName(self, "Assembler-Datei speichern", self.current_dir, "*.asm")
  278.         if file_path:
  279.             if not file_path.endswith(".asm"):
  280.                 file_path += ".asm"
  281.             with open(file_path, 'w', encoding='utf-8') as f:
  282.                 f.write(self.editor_asm.toPlainText())
  283.  
  284. if __name__ == '__main__':
  285.     app = QApplication(sys.argv)
  286.     window = PascalSymbolBrowser()
  287.     window.show()
  288.     sys.exit(app.exec_())
  289.  
MS-IIS - Internet Information Server, Apache, PHP/HTML/CSS, MinGW-32/64 MSys2 GNU C/C++ 13 (-stdc++20), FPC 3.2.2
A Friend in need, is a Friend indeed.

 

TinyPortal © 2005-2018