DelphiC is a comprehensive Delphi wrapper for the Tiny C Compiler (TCC), enabling runtime C code compilation, execution, and bidirectional symbol exchange between Delphi and C code. Compile C code to memory, executables, DLLs, or object files directly from your Delphi applications.
- 💾 In-Memory Compilation - Compile and execute C code at runtime without temporary files
- 📦 Multiple Output Types - Generate EXE, DLL, OBJ files, or preprocess-only mode
- 🔄 Bidirectional Symbols - Call Delphi functions from C and vice versa
- 🛡️ Comprehensive Error Handling - Structured error capture with filename, line numbers, and severity
- 🔐 Workflow Enforcement - State management prevents API misuse and crashes
- ⚙️ Full TCC Options - Direct access to all TCC compiler flags and settings
- 🔗 Multi-Unit Support - Compile and link multiple C source files and object files
- 🎯 Zero Dependencies - Self-contained with embedded TCC, no external tools required
- 🎮 JIT compilation for scripting engines
- 🔌 Dynamic plugin systems with C-based extensions
- 🏗️ Runtime code generation for DSLs
- 📚 Embedding C libraries without separate compilation
- 🎓 Educational tools demonstrating compilation concepts
- 🔀 Language transpilers targeting C as intermediate representation
- OS: Windows 64-bit
- Delphi: Tested on 12.3
- Target: x86_64 only
- Clone the repository:
git clone https://github.com/tinyBigGAMES/DelphiC.git
-
Add the
src
folder to your Delphi library path or project search path -
Add
DelphiC
to your uses clause:
uses
DelphiC;
uses
DelphiC;
procedure HelloWorld;
type
THelloFunc = function(): Integer; cdecl;
var
LCompiler: TDelphiC;
LHello: THelloFunc;
begin
LCompiler := TDelphiC.Create();
try
// Configure for in-memory execution
LCompiler.SetOuput(opMemory);
// Compile C code
LCompiler.CompileString(
'#include <stdio.h>' + #10 +
'int hello() {' + #10 +
' printf("Hello from C!\n");' + #10 +
' return 42;' + #10 +
'}'
);
// Relocate and get function pointer
if LCompiler.Relocate() then
begin
LHello := LCompiler.GetSymbol('hello');
if Assigned(LHello) then
WriteLn('Result: ', LHello());
end;
finally
LCompiler.Free();
end;
end;
// Delphi callback function
function DelphiAdd(A, B: Integer): Integer; cdecl;
begin
Result := A + B;
WriteLn('Delphi says: ', A, ' + ', B, ' = ', Result);
end;
procedure CallbackExample;
type
TTestFunc = function(): Integer; cdecl;
const
CCode =
'int delphi_add(int a, int b);' + #10 +
'int test() {' + #10 +
' return delphi_add(10, 20);' + #10 +
'}';
var
LCompiler: TDelphiC;
LTest: TTestFunc;
begin
LCompiler := TDelphiC.Create();
try
LCompiler.SetOuput(opMemory);
// Inject Delphi function into C
LCompiler.AddSymbol('delphi_add', @DelphiAdd);
LCompiler.CompileString(CCode);
if LCompiler.Relocate() then
begin
LTest := LCompiler.GetSymbol('test');
if Assigned(LTest) then
WriteLn('C called Delphi, result: ', LTest());
end;
finally
LCompiler.Free();
end;
end;
procedure CreateExecutable;
var
LCompiler: TDelphiC;
begin
LCompiler := TDelphiC.Create();
try
LCompiler.SetOuput(opEXE);
LCompiler.SetSubsystem(ssConsole);
LCompiler.CompileString(
'#include <stdio.h>' + #10 +
'int main() {' + #10 +
' printf("Standalone executable!\n");' + #10 +
' return 0;' + #10 +
'}'
);
LCompiler.OutputFile('myapp.exe');
WriteLn('Created myapp.exe');
finally
LCompiler.Free();
end;
end;
procedure MultiFileProject;
var
LCompiler: TDelphiC;
begin
LCompiler := TDelphiC.Create();
try
// Compile unit1 to object file
LCompiler.SetOuput(opOBJ);
LCompiler.CompileString('int add(int a, int b) { return a + b; }');
LCompiler.OutputFile('unit1.o');
// Reset and link everything
LCompiler.Reset();
LCompiler.SetOuput(opEXE);
LCompiler.AddFile('unit1.o'); // Link compiled object
LCompiler.CompileString('int add(int, int); int main() { return add(2, 3); }');
LCompiler.OutputFile('program.exe');
finally
LCompiler.Free();
end;
end;
Method | Description |
---|---|
Create() |
Initialize TCC compilation context |
Reset() |
Reset compiler for reuse |
SetOuput(TDCOutput) |
Set output type (Memory/EXE/DLL/OBJ/Preprocess) |
CompileString(code, filename) |
Compile C source from string |
AddFile(filename) |
Add C source, object file, or library |
Relocate() |
Prepare for in-memory execution |
GetSymbol(name) |
Retrieve function/variable pointer |
AddSymbol(name, ptr) |
Inject Delphi symbols into C |
OutputFile(filename) |
Generate output file |
Run(argc, argv) |
Execute compiled program |
Method | Description |
---|---|
SetOption(option) |
Set any TCC command-line option |
SetDebugInfo(enabled) |
Enable debug information (-g) |
DisableWarnings() |
Suppress all warnings (-w) |
SetWarningsAsErrors() |
Treat warnings as errors (-Werror) |
SetSubsystem(TDCSubsystem) |
Set Windows subsystem (Console/GUI) |
DefineSymbol(sym, val) |
Define preprocessor symbol |
AddIncludePath(path) |
Add include directory |
AddLibraryPath(path) |
Add library search path |
AddLibrary(name) |
Link against library |
Method | Description |
---|---|
SetPrintCallback(handler) |
Register error/warning callback |
GetErrors() |
Retrieve structured error list |
ClearErrors() |
Clear accumulated errors |
DelphiC supports all TCC Win64 options via SetOption()
:
📝 Preprocessor: -I
, -D
, -U
, -E
⚡ Compilation: -funsigned-char
, -fsigned-char
, -fms-extensions
-w
, -Wall
, -Werror
, -Wimplicit-function-declaration
🔗 Linking: -L
, -l
, -Wl,-subsystem=
, -Wl,-stack=
🐛 Debug: -g
(bounds checking -b
not supported on Win64)
🎯 Target: -mms-bitfields
, -mno-sse
See full documentation in source code XML comments.
SetOutput(opMemory) → CompileString → [AddSymbol] → Relocate → GetSymbol
SetOutput(opEXE/DLL/OBJ) → CompileString → [AddSymbol] → OutputFile
SetOutput(opEXE) → CompileString → Run(argc, argv)
LCompiler.SetPrintCallback(
nil,
procedure(const AError: string; const AUserData: Pointer)
begin
WriteLn('[TCC] ', AError);
end
);
if not LCompiler.CompileString(CCode) then
begin
var LErrors := LCompiler.GetErrors();
for var LError in LErrors do
WriteLn(LError.Filename, ':', LError.Line, ': ', LError.Message);
end;
See the examples/
directory for:
- ✅ Basic compilation and execution
- 🔄 Callback integration
- 📦 Multi-unit projects
- 🚨 Error handling patterns
- 📖 Dynamic library creation
- 🪟 Win64 only - No 32-bit or other platform support
- 🚫 No bounds checking - The
-b
flag causes crashes on Win64 - 🔧 No optimization flags - TCC ignores
-O
options (single-pass compiler) - 📜 C99 standard - Some C11/C23 features may not be supported
- 🚷 No C++ - Pure C compilation only
DelphiC uses a state machine to enforce correct TCC API usage:
🆕 New → ⚙️ Configured → ✅ Compiled → 🚀 Relocated/Finalized
Invalid state transitions return False
and prevent crashes from TCC API misuse.
- Open
DelphiC - Runtime C compilation for Delphi.groupproj
insrc
folder - in
UTestbed.pas
, setLNum
to test number to run - Build an run
No external dependencies required - TCC is embedded as a compiled object.
Contributions are welcome! Please:
- 🍴 Fork the repository
- 🌿 Create a feature branch
- 📝 Follow existing code style
- ✅ Add tests for new features
- 💾 Commit changes
- 📤 Push to branch
- 🔀 Open a Pull Request
DelphiC is released under the BSD 3-Clause License.
Copyright © 2025-present tinyBigGAMES™ LLC. All Rights Reserved.
See LICENSE for full license text.
This library uses:
- TCC (Tiny C Compiler) - https://github.com/TinyCC/tinycc
- 🐛 Issues: GitHub Issues
- 💭 Discussions: GitHub Discussions
- Fabrice Bellard - Original TCC author
- TCC Contributors - Ongoing TCC development
- Delphi Community - Testing and feedback
Made with ❤️ by tinyBigGAMES™
"Bridging Delphi and C at runtime"