Plugin development
This page is for developers who want to add new file format support (Type plugins) or extend GView. Use the public API only; internal APIs are not stable for plugins.
Public vs internal API
GView.hpp (
GViewCore/include/GView.hpp) — Public API. All types, interfaces, and utilities for plugins live here. Plugins must rely only on this header.Internal.hpp (
GViewCore/src/include/Internal.hpp) — Private implementation. Used only inside GViewCore. Do not use in Type or Generic plugins.
Type plugin contract
Every Type plugin must export these C functions (extern "C"):
Validate — Return whether a buffer matches this file type (magic, extension, etc.).
CreateInstance — Return a new instance of your TypeInterface implementation.
PopulateWindow — Configure viewers and panels for the opened file.
UpdateSettings — Register patterns, priority, and commands in the INI layer.
Your plugin class must inherit GView::TypeInterface and implement:
GetTypeName() — Plugin display name.
RunCommand(string_view) — Handle custom commands (e.g. from menus).
UpdateKeys(KeyboardControlsInterface*) — Register keyboard shortcuts.
GetSmartAssistantContext(…) — Provide context for the smart assistant (can return minimal JSON).
Keyboard shortcuts
Every key handled by a plugin must be a named KeyboardControl (AppCUI::Input::KeyBinding) so that it is listed
in the Keyboard shortcuts window (F1) and can be changed by the user (see Keyboard shortcuts):
namespace GView::Type::MyType
{
// `inline` -> a single object shared by every .cpp file of the plugin (the registry writes the user key into it)
inline KeyboardControl MY_COMMANDS[] = {
{ Input::Key::Alt | Input::Key::F8, "Verify", "Verify the signature", MY_COMMAND_VERIFY },
};
inline GView::StandardPanelKeys PANEL_KEYS; // F9 Select / F2 Dec-Hex of the list panels
inline KeyboardControl PANEL_OPEN = { Input::Key::Ctrl | Input::Key::O, "PanelOpen", "Open the current entry", 0 };
}
bool MyTypeFile::UpdateKeys(KeyboardControlsInterface* interface)
{
for (auto& cmd : MY_COMMANDS)
interface->RegisterKey(&cmd);
PANEL_KEYS.Register(interface); // starts the "Panels" category
interface->RegisterKey(&PANEL_OPEN);
return true;
}
Rules:
The
Captionis the identifier saved in the settings - keep it stable and unique for the plugin.Commands executed through
RunCommandare declared inUpdateSettingsasCommand.<Caption>usingDefaultKey(sect["Command.Verify"] = cmd.DefaultKey;) and registered inUpdateKeyswith the same caption.Read the key when it is used (
commandBar.SetCommand(PANEL_OPEN.Key, "Open", ID),PANEL_OPEN.Matches(keyCode)), never copy it at construction time.Matchesnever matches an unassigned (Key::None) shortcut.interface->BeginCategory("Panels")groups keys in the window; panel categories must start withPanel(e.g."Panel: Resources") - keys of different panel categories are never reported as conflicts.interface->RegisterKeyText("0-9", "Bookmarks", "...")lists keys that can not be configured (character keys, keys handled by AppCUI controls).Keys of modal dialogs are shown in the dialog command bar and are not registered.
The KeyboardControl layout and the KeyboardControlsInterface virtual table are part of the plugin ABI: changing
them requires rebuilding GViewCore, AppCUI and every plugin.
Smart viewers
Each Type plugin chooses which viewers to create in PopulateWindow. Available
viewers and their settings classes:
BufferViewer — Hex/binary with zones, colors, bookmarks. Settings:
GView::View::BufferViewer::SettingsTextViewer — Plain text with line wrapping. Settings:
GView::View::TextViewer::SettingsLexicalViewer — Syntax-highlighted code with folding. Settings:
GView::View::LexicalViewer::SettingsImageViewer — Image display. Settings:
GView::View::ImageViewer::SettingsGridViewer — Tabular data (CSV, etc.). Settings:
GView::View::GridViewer::SettingsDissasmViewer — Disassembly (Capstone) with type annotations. Settings:
GView::View::DissasmViewer::SettingsContainerViewer — Tree view for archives / container content. Settings:
GView::View::ContainerViewer::Settings
Key interfaces
Object — The opened file, buffer, or process. From TypeInterface you get
obj (pointer to Object). Use obj->GetData() for a DataCache& and
obj->GetName() / obj->GetPath() for identification.
DataCache — Cached access to file/buffer data. Use Get(offset, size, failIfCannotRead)
for a BufferView, CopyToBuffer(...) for a copy, and Copy<T>(offset, object) to
read a struct. GetSize() gives the total size.
WindowInterface — In PopulateWindow you receive a Reference<WindowInterface>.
Call GetObject() to get the Object, CreateViewer(settings) for each viewer,
and AddPanel(Pointer<TabPage>(...), vertical) for custom panels.
Adding a new Type plugin
Create a directory under
Types/YOUR_PLUGIN/(e.g.Types/MyFormat/).Add
include/your_plugin.hppwith your TypeInterface implementation.Add
src/your_plugin.cpp(and optional panels) with the exported functions (Validate, CreateInstance, PopulateWindow, UpdateSettings).Add a
CMakeLists.txt(copy from an existing Type such asTypes/PREFETCH).In the repository root
CMakeLists.txt, addadd_subdirectory(Types/YOUR_PLUGIN).
Coding conventions
C++20 — Required (set in CMake).
Naming — PascalCase for types and functions, camelCase for variables.
Strings — Prefer
std::string_view; useFixSizeString<N>orLocalString<N>for fixed/stack buffers.Pointers — Use
Reference<T>(non-owning) andPointer<T>(owning) from AppCUI; avoid rawnew/delete.Errors — Use
CHECK(condition, returnValue, "message")for validation;GView::Utils::ErrorListfor multiple errors;GView::Utils::GStatuswhen returning a status message.Data access — Use
DataCacheandBufferView; avoid unnecessary copies.
Common patterns
Creating viewers in PopulateWindow
Get your type from the window, configure the settings (zones, callbacks), then create the viewer and add panels:
PLUGIN_EXPORT bool PopulateWindow(Reference<GView::View::WindowInterface> win) {
auto myType = win->GetObject()->GetContentType<MyTypeFile>();
BufferViewer::Settings settings;
settings.AddZone(0, sizeof(Header), ColorPair{Color::White, Color::DarkBlue}, "Header");
settings.SetPositionToColorCallback(myType.ToBase<BufferViewer::PositionToColorInterface>());
win->CreateViewer(settings);
win->AddPanel(Pointer<TabPage>(new MyPanel(myType, win)), true);
return true;
}
Reading file data
Use Object::GetData() to get a DataCache&. Use Copy<T> for structs and
Get() for variable-length data:
bool MyTypeFile::Update() {
auto& data = obj->GetData();
if (!data.Copy<MyHeader>(0, header)) return false;
auto buf = data.Get(offset, size, true);
if (!buf.IsValid()) return false;
return true;
}
When a library or OS API needs a real file and the object is not Object::Type::File (e.g. it was extracted from
a container), use GView::App::DropToTemporaryFile. Never write the content next to the container or under a
path built from the object’s path. The copy lives in GView’s private temporary folder (see GView configuration file) and
is deleted when the TemporaryFile handle is destroyed. Close the file before that happens. The call fails
(silently) for Learning and Evaluation Mode content that must stay in memory, so always keep a fallback:
GView::App::TemporaryFile copy;
if (auto status = GView::App::DropToTemporaryFile(obj, copy); status.ok) {
VerifyWithAnApiThatNeedsAFile(copy.GetPath());
} else {
// in-memory processing, or report status.message
}
PositionToColorInterface (buffer highlighting)
Implement this interface so the buffer viewer can color ranges by offset:
bool MyTypeFile::GetColorForBuffer(uint64 offset, BufferView buf, BufferColor& result) {
if (offset >= section.start && offset < section.end) {
result.start = section.start;
result.end = section.end;
result.color = ColorPair{Color::Yellow, Color::DarkRed};
return true;
}
result.Reset();
return false;
}
Generic plugins
Generic plugins work with any file type and are registered via GView.ini
(see GView configuration file). They usually provide dialogs or operations (e.g. hashes,
entropy, comparison). Implement them under GenericPlugins/ and register in INI;
they do not implement the Type plugin contract above.
Quick reference
Add new file format —
Types/NEW_TYPE/— TypeInterface, Validate, PopulateWindowAdd generic operation —
GenericPlugins/— Window-based dialogsAdd hash algorithm —
GViewCore/src/Hashes/— Hash classes in GView.hppAdd decoding —
GViewCore/src/Decoding/— Decoding namespaceModify viewer behavior —
GViewCore/src/View/— ViewControl, SettingsAdd keyboard shortcut — TypeInterface —
inline KeyboardControl+ UpdateKeys() (see Keyboard shortcuts)Add panel to Type —
Types/*/src/Panel*.cpp— TabPage, ListViewAI assistant context — TypeInterface — GetSmartAssistantContext()