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.