BindingC_Dll_Pascal_Python
convert an .h dll in Pascal Or python unit to automatically bind the dll.
- Active · last change 4-27-2026
- ★ 1 on GitHub
README
H2Pas Converter
A Lazarus GUI tool that converts C header files (.h) into ready-to-use Pascal (FPC) or Python (ctypes) binding units — in one click.
Table of Contents
- What It Does
- Features
- Supported C Constructs
- Prerequisites
- Build from Source
- First Run
- Usage
- Example
- Project Structure
- Known Limitations
- Troubleshooting
- Documentation
- Contributing
- License
- About
What It Does
Instead of manually translating each typedef struct, typedef enum, #define, and function prototype from C to Pascal or Python, H2Pas Converter does it automatically:
- Pascal mode → generates a complete
.pasunit with external declarations andcdeclcalling convention - Python mode → generates a
.pymodule withctypesCDLL, Structure subclasses, andargtypes/restypedeclarations
Features
✅ Automatic type mapping — 26 C types mapped to Pascal / ctypes equivalents
✅ Preprocessor — #define integer, float, and string constants converted
✅ Structs — typedef struct → Pascal record with {$PACKRECORDS C} / Python Structure
✅ Enums — typedef enum → Pascal integer type + constants / Python integer constants
✅ Opaque handles — typedef struct Foo_t* Foo → Pointer / c_void_p
✅ Functions — full external … name … / argtypes + restype output
✅ Pointer params — Circle* → PCircle (Pascal) / POINTER(Circle) (Python)
✅ const char* → PAnsiChar / c_char_p
✅ void return → procedure (Pascal) / restype = None (Python)
✅ Dual output — switch language with a radio button, no restart needed
✅ Save dialog — pre-fills filename and extension from the Unit field
✅ Conversion log — detailed journal of every element processed
Supported C Constructs
| C Construct | Pascal Output | Python Output |
|---|---|---|
#define FOO 42 |
const FOO = 42; |
FOO = 42 |
typedef struct { … } Name; |
Name = record … end; |
class Name(Structure): _fields_ = […] |
typedef enum { A=0 } Name; |
Name = LongInt; const A=0; |
A = 0 |
typedef struct Foo_t* Foo; |
Foo = Pointer; |
Foo = c_void_p |
int32_t __cdecl fn(…); |
function fn(…): LongInt; cdecl; external … |
lib.fn.argtypes = […]; lib.fn.fn.restype = c_int32 |
void __cdecl fn(…); |
procedure fn(…); cdecl; external … |
lib.fn.restype = None |
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| Lazarus | 4.x (tested 4.6) | IDE for development and UI design |
| Free Pascal Compiler | 3.2.x | Compiler for Pascal code |
| Windows | 64-bit | Target operating system |
| RAM | 2GB minimum | For comfortable development |
Build from Source
- Clone or download this repository:
git clone https://github.com/axel18bsm/BindingC_Dll_Pascal_Python.git cd BindingC_Dll_Pascal_Python - Open the project in Lazarus:
- Open
H2PasConverter\H2PasConverter.lpiin Lazarus IDE
- Open
- Build & Run:
- Press
F9or go to Run → Build & Run
- Press
- First Build Notes:
- If Lazarus reports a missing
.resfile:- Either: uncomment
{$R *.res}inH2PasConverter.lprafter Lazarus generates it - Or: leave it commented — the application runs without it
- Either: uncomment
- If Lazarus reports a missing
First Run
- The application window will open with three main panels:
- Left panel: C header file input (browse or paste code)
- Center panel: Settings (DLL name, Unit name, target language)
- Right panel: Generated output code
- Bottom panel: Conversion log
Usage
- Load a C header file:
- Click
[…]to browse for a.hfile, or paste C code directly into the Source panel
- Click
- Configure binding settings:
- Verify the DLL name (e.g.,
raylib.dll) - Verify the Unit name (auto-filled from filename)
- Verify the DLL name (e.g.,
- Select target language:
- Choose Pascal (FPC) or Python (ctypes)
- Generate bindings:
- Click CONVERT
- Review output:
- Check the result in the right panel
- Review the log at the bottom for any warnings or errors
- Save the file:
- Click Save .pas… (for Pascal) or Save .py… (for Python) to write to disk
Example
Input (mylib.h)
#define MYLIB_VERSION 200
typedef struct {
int32_t x;
int32_t y;
float radius;
} Circle;
typedef enum {
ERR_OK = 0,
ERR_FAIL = 1
} ErrorCode;
typedef struct MyHandle_t* MyHandle;
int32_t __cdecl mylib_add(int32_t a, int32_t b);
MyHandle __cdecl mylib_open(const char *filename);
ErrorCode __cdecl mylib_process(MyHandle h, Circle c);
void __cdecl mylib_close(MyHandle h);Pascal Output (uMylibBinding.pas)
unit uMylibBinding;
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
SysUtils;
const
MYLIB_VERSION = 200;
type
Circle = record
x: LongInt;
y: LongInt;
radius: Single;
end;
PCircle = ^Circle;
ErrorCode = LongInt;
MyHandle = Pointer;
const
ERR_OK = 0;
ERR_FAIL = 1;
function mylib_add(a: LongInt; b: LongInt): LongInt; cdecl;
external 'mylib.dll' name 'mylib_add';
function mylib_open(filename: PAnsiChar): Pointer; cdecl;
external 'mylib.dll' name 'mylib_open';
function mylib_process(h: Pointer; c: Circle): LongInt; cdecl;
external 'mylib.dll' name 'mylib_process';
procedure mylib_close(h: Pointer); cdecl;
external 'mylib.dll' name 'mylib_close';
implementation
end.Python Output (mylib.py)
from ctypes import c_int32, c_float, c_char_p, c_void_p, POINTER, Structure, CDLL
lib = CDLL("mylib.dll")
MYLIB_VERSION = 200
class Circle(Structure):
_fields_ = [("x", c_int32), ("y", c_int32), ("radius", c_float)]
ERR_OK = 0
ERR_FAIL = 1
MyHandle = c_void_p
lib.mylib_add.argtypes = [c_int32, c_int32]
lib.mylib_add.restype = c_int32
lib.mylib_open.argtypes = [c_char_p]
lib.mylib_open.restype = c_void_p
lib.mylib_process.argtypes = [c_void_p, Circle]
lib.mylib_process.restype = c_int32
lib.mylib_close.argtypes = [c_void_p]
lib.mylib_close.restype = NoneProject Structure
H2PasConverter/
????????? H2PasConverter.lpi # Lazarus project file
????????? H2PasConverter.lpr # Application entry point
????????? uMainForm.pas # GUI form ??? orchestration
????????? uMainForm.lfm # GUI form design
????????? uCHeaderParser.pas # C header parsing logic
????????? uTypeMapper.pas # C ??? Pascal/Python type mapping
????????? uPascalGenerator.pas # Pascal code generation
????????? uPythonGenerator.pas # Python code generation
????????? README.md # This fileKnown Limitations
⚠️ cdecl only — stdcall (Win32 API) functions are not auto-detected; add the keyword manually after generation
⚠️ Simple macros only — function-like macros (#define MAX(a,b) …) are ignored
⚠️ No C++ templates — pure C headers only (no C++ templates or namespaces)
⚠️ No bitfields — bitfield structs are not supported
⚠️ No GCC extensions — __attribute__ and other compiler-specific extensions not supported
Troubleshooting
Issue: "Cannot find Lazarus project file"
Solution: Ensure you extracted all files correctly and the .lpi file exists in the H2PasConverter directory.
Issue: "Missing .res file on first build"
Solution:
- Let Lazarus auto-generate the
.resfile - Or uncomment
{$R *.res}inH2PasConverter.lpr - The application works fine without it
Issue: "DLL not found at runtime"
Solution:
- Ensure the DLL file path is correct and the DLL exists
- Copy the DLL to the same directory as your generated binding unit
- Or provide the full path in the binding unit's
externaldeclaration
Issue: "Type mapping is incorrect"
Solution:
- Check the conversion log in the bottom panel for warnings
- Verify the C header syntax is correct
- Report any issues on GitHub with the problematic C code
Issue: "Generated code won't compile in Pascal"
Solution:
- Check that Free Pascal 3.2.x is installed and in your PATH
- Verify all referenced units (like
SysUtils) exist - For linking issues, ensure
{$PACKRECORDS C}is present
Issue: "Python module import fails"
Solution:
- Ensure
ctypesis available (included in Python stdlib) - Check that the DLL path in
CDLL("…")is correct - Verify the DLL architecture matches your Python installation (32-bit or 64-bit)
Documentation
| Document | Language | Contents |
|---|---|---|
| H2PasConverter_Documentation.docx | French | User guide · DLL binding course · Technical reference |
| H2PasConverter_Documentation_EN_Vol1.docx | English | User guide · Technical reference |
| H2PasConverter_Documentation_EN_Vol2.docx | English | DLL binding course (theory, type tables, examples, pitfalls) |
| Etape1_Fondamentaux_Binding_DLL.docx | French | DLL binding fundamentals reference |
Contributing
We welcome contributions! To contribute:
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-improvement - Make your changes and test thoroughly
- Commit with clear messages:
git commit -m "Add support for …" - Push to your fork:
git push origin feature/my-improvement - Open a Pull Request with a clear description
Reporting Bugs
If you find a bug:
- Check if it's already reported in Issues
- Create a new issue with:
- Your C header file (or example)
- Expected vs. actual output
- Your Lazarus/FPC versions
- Steps to reproduce
License
MIT — free to use, modify, and distribute.
About
Built as a learning tool for the tutorial series "Learning to Bind a C DLL in Pascal".
Target stack: Free Pascal 3.2 · Lazarus 4.x · Windows 64-bit · cdecl calling convention

