C++ SDK

This page describes basic steps needed to create a new custom command with C++ SDK that reads two integer arguments and returns their sum. This guide has been tested on Visual Studio 2019 and Visual Studio 2022 (Community Edition) and may differ for other IDEs and compilers.

Developing a Plugin

  • Create a new Dynamic-link Library (DLL) project. In Project Settings->Advanced set Target File Extension to .cleo.

  • Download cleo_redux_sdk.h and add it in your project

#include "cleo_redux_sdk.h"

If this header file is located outside of your project directory you need to add a folder with this file in Project Settings->VC++ Directories->Include Directories to let Visual Studio discover this file.

  • In Project Settings->Linker->Input add the full path to cleo_redux.lib (if you develop a 32-bit plugin) or to cleo_redux64.lib for 64-bit plugins.

  • in dllmain.cpp create a new static class with the constructor function. This constructor will be called as soon as CLEO loads your plugin

class TestPlugin {
public:
	TestPlugin() {
		Log("My Test Plugin");
	}
} TestPlugin;
  • in the plugin class constructor call RegisterCommand function for each new command
class TestPlugin {
public:
	TestPlugin() {
		Log("My Test Plugin");
        RegisterCommand("INT_ADD", IntAdd);
	}

    static HandlerResult IntAdd(Context ctx) {
        return HandlerResult::CONTINUE;
    }
} TestPlugin;
  • implement handlers for new commands. Each command handler gets one input argument which is Context ctx. This argument is used to call other SDK methods
class TestPlugin {
public:
	TestPlugin() {
		Log("My Test Plugin");
        RegisterCommand("INT_ADD", IntAdd);
	}

    static HandlerResult IntAdd(Context ctx) {
        auto arg1 = GetIntParam(ctx);
        auto arg2 = GetIntParam(ctx);
        SetIntParam(ctx, arg1 + arg2);

        return HandlerResult::CONTINUE;
    }
} TestPlugin;
  • compile the project and place .cleo file to the CLEO_PLUGINS folder.

  • add command definition in the JSON file for the target game (e.g. gta3.json for GTA III or unknown_x86.json for an Unknown (x86) host). Each GetXXXParam/SetXXXParam should be paired with an input or output in the command definition

{
    "input": [
        { "name": "arg1", "type": "int" },
        { "name": "arg2", "type": "int" }
    ],
    "output": [
        { "name": "result", "type": "int", "source": "var_any" }
    ],
    "id": "0DDD",
    "name": "INT_ADD",
    "num_params": 3,
    "short_desc": "Adds together two integer values and writes the result into the variable",
},

id is optional for unknown hosts. For known and supported games an id must be a unique opcode not used elsewhere.

The best way to generate correct command definition is to use Sanny Builder Library. If you plan to share the plugin and make it available over the Internet consider contacting the library maintainers to get your command published there.

  • you can now use the new command in the code using the native command
var result = native("INT_ADD", 10, 20); // 30

Example

See the IniFiles plugin that includes a complete project for Visual Studio 2019.