You can try to use the setContextObject method of the QQmlContext if the QQmlEngine you are using. I created a minimal Gist which demonstrates the approach.
Basically, you create a custom class deriving from QObject, say, MyApi:
class MyAPI : public QObject
{
    Q_OBJECT
public:
    explicit MyAPI(QObject *parent = nullptr);
    // This method will be visible as function in your QML code:
    Q_INVOKABLE QString makeUpperCase(const QString &text) const;
};
In you main.cpp, set an instance of this class as the context object of the engine's QQmlContext:
QQmlApplicationEngine engine;
engine.rootContext()->setContextObject(new MyAPI(&app));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
In the QML code, you can now access all properties, signals, slots and Q_INVOKABLE methods of the MyAPI class:
Window {
    visible: true
    width: 640
    height: 480
    // Call the `makeUpperCase` method of the context object:
    title: makeUpperCase("Hello World")
}