Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

DaiC features a modular plugin architecture, allowing developers to extend core functionality. You can find official examples and community contributions in our Github repository. Supported Languages

We currently support two types of plugin implementations:

  • Python: Ideal for rapid development and scripting.
  • C++: Best for performance-intensive tasks.

Installation Methods

You can load plugins into DaiC using one of the following methods:

  • In-App Interface: Use the built-in Plugin Manager within the DaiC UI.
  • Manual Installation: Drop your plugin folder into the specific language directory: APP_DATA_PATH/plugins/{language}/{plugin_name}

Development Requirements

To ensure the loader identifies your plugin correctly, the Plugin Name, Folder Name, and Library Name (for C++) must be identical.

C++ Plugin Development

DaiC utilizes the Qt PluginLoader system to dynamically load C++ extensions. Dependencies

To build a compatible plugin, you must link against the DaiC core:

  • Library: Link against DaiCCoreCpp.
  • Headers: Include the DaiCCore headers in your project path.

The Plugin Interface

Every plugin must inherit from the Plugin base class and use the Qt metadata macros. C++

#include <DaiCCore/Plugin.hpp>
#include <QObject>

class Example : public QObject, public Plugin {
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "com.DaiC.Plugin")
    Q_INTERFACES(Plugin)

public:
    // Lifecycle Methods
    void init() override;
    void run() override;
    void terminate() override;

    // Metadata Methods
    std::string name() const override;        // Must match folder/library name
    std::string author() const override;
    std::string description() const override;
    std::string version() const override;
};

Deployment Structure

The loader is strict about naming conventions. The class name, the containing folder, and the compiled binary must all share the same name.

Example Structure:

plugins/
└── cpp/
    └── Example/            <-- Folder Name
        └── libExample.so   <-- Binary Name (Example.dll on Windows)

On Linux, ensure your library is prefixed with lib. On Windows, the loader expects Example.dll.

Python Plugin Development

DaiC leverages pybind11 to bridge the Python environment with the core C++ engine.

Prerequisites

Before developing, ensure you have the DaiC Python bindings installed in your environment:

pip install DaiCCore

The Plugin Class

Your plugin must be structured as a Python package (a directory containing an init.py file). Inside, you must define a class that inherits from DaiCCore.Plugin. Python

import DaiCCore

class Example(DaiCCore.Plugin):
    # Metadata
    name = "Example"         # Must match the folder name
    description = "A brief description of your plugin"
    version = "1.0.0"
    author = "Your Name"

    def init(self):
        """Called when the plugin is first loaded."""
        pass

    def run(self):
        """Main execution logic for the plugin."""
        pass

    def terminate(self):
        """Cleanup logic before the plugin is unloaded."""
        pass

Dependency Management

DaiC features an automated dependency resolver. If your plugin requires external libraries (like requests or numpy), simply include a standard requirements.txt file in your plugin folder.

Workflow:

  • Detection: On startup, DaiC scans for requirements.txt.
  • Installation: Missing dependencies are automatically installed via pip into the DaiC virtual environment.
  • Isolation: This ensures your plugin has everything it needs to run without manual user intervention.

Directory Example

plugins/
└── python/
    └── Example/
        ├── __init__.py      <-- Contains the Example class
        └── requirements.txt <-- Optional dependencies

Strict Naming: Just like C++ plugins, the Python class name must be identical to the folder name.

Example

The fastest way to develop for DaiC is to bootstrap your project using our official templates.

Exposed Functions

The following functions are made available to plugins through the DaiCCore module. They are exposed via pybind11 and serve various purposes, such as plugin registration, UI interaction, and docking components into the main interface.

See the following sub-sections for usage details.

Registering a Plugin

To define a plugin, call DaiCCore.register() from your plugin’s __init__.py script:

DaiCCore.register(name, description, function)
  • name – A short name to identify your plugin.
  • description – A short description of what your plugin does.
  • function – A callable (usually a function) that will be executed when the plugin is run.

Example:

def run():
    print("Plugin executed.")

DaiCCore.register("MyPlugin", "Demonstrates registration", run)

User Interaction in Plugins

Plugins can interact with users in several ways:

Terminal-Based Interaction

You can use standard Python functions like print() and input():

name = input("What is your name? ")
print(f"Hello, {name}")

This works well in console-based environments.

Built-In UI Components

DaiC provides several ready-to-use dialog functions exposed through DaiCCore:

  • get_file() – Opens a file chooser dialog.
  • input_dialog(title=“”) – Shows a text input dialog.
  • print_dialog(text, title=“”) – Displays a message box.
  • print_markdown_dialog(text, title=“”) – Displays rich text with Markdown formatting.

These are Qt-based and provide a GUI interface without needing to write custom widgets.

Custom Qt UI (Advanced)

You may create your own UI using PySide6 (Qt for Python).

Docking UI Elements

Plugins can integrate buttons into the DaiC interface using:

  • add_to_menu(name, items) – Adds a menu with clickable actions.
  • add_to_tool(name, action) – Adds a button to the main toolbar.

Example usage:

def on_click():
    print("Toolbar button clicked!")

DaiCCore.add_to_tool("Click Me", on_click)

You can also use add_to_menu() to register dropdown menu items with labels and actions.

Binary Information

DaiC provides a set of functions to query information about the binary currently being analyzed.
This can be useful when writing analysis or reverse-engineering oriented plugins.

Get Imported Functions

The function:

DaiCCore.get_imports()

Returns a list of imported functions. Each imported function is represented using the following C++ structure:

struct ImportedFn {
    unsigned offset;        // Offset of the function in memory
    std::string file_name;  // Library or object file providing the symbol
    std::string fonction_name; // Name of the imported function
};

In Python, the result is automatically converted into a list of objects with equivalent fields.

Example

imports = DaiCCore.get_imports()
for fn in imports:
    print(f"0x{fn.offset:x} {fn.file_name}::{fn.fonction_name}")

Connecting Signals

DaiC allows you to connect custom Python functions to certain UI signals.
This makes it possible to react to user actions in the interface.

Dissasm function list

DaiCCore.connect_dissasm_view(function)
  • function: a Python callback that receives a single string argument.

The string corresponds to the currently selected disassembly line, in this format:

0x00000000000011EF:	call		0x1dcb

Example

import DaiCCore

def on_selection_changed(line: str):
    print("Selected instruction:", line)

    DaiCCore.connect_dissasm_view(on_selection_changed)

Whenever the user changes the selection in the disassembly view, the function on_selection_changed will be called with the text of the selected line.

Notes & Limitations:

  • More signals may be exposed in future versions of DaiC (menus, editors, etc.).
  • Since Qt UI elements are involved, avoid creating or modifying widgets in these callbacks from non-main threads.