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 srcfolder to your Delphi library path or project search path
- 
Add DelphiCto 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 -bflag causes crashes on Win64
- 🔧 No optimization flags - TCC ignores -Ooptions (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.groupprojinsrcfolder
- in UTestbed.pas, setLNumto 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"
