Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Debug.Log from C++

Tags:

c++

c#

unity3d

When making C++ plugins in Unity it is easier to use Debug.Log to quickly view variable values but this function is only available from C# side. This makes it very hard to debug C++ plugin since Unity's debugger does not support that. std::cout is not an option since it doesn't show in the Editor.

I looked inside the Unity C++ API located at <UnityInstallationDirecory>\Editor\Data\PluginAPI but didn't find anything about logging in the API.

Any suggestions on how to display in the Editor log from C++?

like image 420
Programmer Avatar asked May 02 '17 07:05

Programmer


People also ask

How do I use debug logs?

To view a debug log, from Setup, enter Debug Logs in the Quick Find box, then select Debug Logs. Then click View next to the debug log that you want to examine. Click Download to download the log as an XML file. Debug logs have the following limits.

What does debug log Do C#?

Use Debug. Log to print informational messages that help you debug your application. For example, you could print a message containing a GameObject.name and information about the object's current state.

What is a debug log?

A debug log can record database operations, system processes, and errors that occur when executing a transaction or running unit tests. Debug logs can contain information about: Database changes. HTTP callouts.

What is the difference between debug log and print?

Print() essentially calls Debug. Log() so there are no major differences. One thing to remember though is that Print() is inherited from the MonoBehaviour class so if you create a class that doesn't inherit from it(this is first done in the BowlMaster) then Print() will no longer work.


1 Answers

This can be done with a callback function. Send a pointer to a function to from C# to C++ store it in a temporary variable. Put Debug.Log inside that callback function and allow it to receive strings as a pointer(IntPtr).

When this function is called from C++, convert the IntPtr to string with Marshal.PtrToStringAnsi.

To make it work on iOS you have to use the MonoPInvokeCallback attribute on the callback function.

C# (Attach to an empty GameObject):

using AOT;
using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class DebugCPP : MonoBehaviour
{

    // Use this for initialization
    void OnEnable()
    {
        RegisterDebugCallback(OnDebugCallback);
    }

    //------------------------------------------------------------------------------------------------
    [DllImport("DebugLogPlugin", CallingConvention = CallingConvention.Cdecl)]
    static extern void RegisterDebugCallback(debugCallback cb);
    //Create string param callback delegate
    delegate void debugCallback(IntPtr request, int color, int size);
    enum Color { red, green, blue, black, white, yellow, orange };
    [MonoPInvokeCallback(typeof(debugCallback))]
    static void OnDebugCallback(IntPtr request, int color, int size)
    {
        //Ptr to string
        string debug_string = Marshal.PtrToStringAnsi(request, size);

        //Add Specified Color
        debug_string =
            String.Format("{0}{1}{2}{3}{4}",
            "<color=",
            ((Color)color).ToString(),
            ">",
            debug_string,
            "</color>"
            );

        UnityEngine.Debug.Log(debug_string);
    }
}

C++ (DebugCPP.h):

#pragma once
#include<stdio.h>
#include <string>
#include <stdio.h>
#include <sstream>

#define DLLExport __declspec(dllexport)

extern "C"
{
    //Create a callback delegate
    typedef void(*FuncCallBack)(const char* message, int color, int size);
    static FuncCallBack callbackInstance = nullptr;
    DLLExport void RegisterDebugCallback(FuncCallBack cb);
}

//Color Enum
enum class Color { Red, Green, Blue, Black, White, Yellow, Orange };

class  Debug
{
public:
    static void Log(const char* message, Color color = Color::Black);
    static void Log(const std::string message, Color color = Color::Black);
    static void Log(const int message, Color color = Color::Black);
    static void Log(const char message, Color color = Color::Black);
    static void Log(const float message, Color color = Color::Black);
    static void Log(const double message, Color color = Color::Black);
    static void Log(const bool message, Color color = Color::Black);

private:
    static void send_log(const std::stringstream &ss, const Color &color);
};

C++ (DebugCPP.cpp):

#include "DebugCPP.h"

#include<stdio.h>
#include <string>
#include <stdio.h>
#include <sstream>

//-------------------------------------------------------------------
void  Debug::Log(const char* message, Color color) {
    if (callbackInstance != nullptr)
        callbackInstance(message, (int)color, (int)strlen(message));
}

void  Debug::Log(const std::string message, Color color) {
    const char* tmsg = message.c_str();
    if (callbackInstance != nullptr)
        callbackInstance(tmsg, (int)color, (int)strlen(tmsg));
}

void  Debug::Log(const int message, Color color) {
    std::stringstream ss;
    ss << message;
    send_log(ss, color);
}

void  Debug::Log(const char message, Color color) {
    std::stringstream ss;
    ss << message;
    send_log(ss, color);
}

void  Debug::Log(const float message, Color color) {
    std::stringstream ss;
    ss << message;
    send_log(ss, color);
}

void  Debug::Log(const double message, Color color) {
    std::stringstream ss;
    ss << message;
    send_log(ss, color);
}

void Debug::Log(const bool message, Color color) {
    std::stringstream ss;
    if (message)
        ss << "true";
    else
        ss << "false";

    send_log(ss, color);
}

void Debug::send_log(const std::stringstream &ss, const Color &color) {
    const std::string tmp = ss.str();
    const char* tmsg = tmp.c_str();
    if (callbackInstance != nullptr)
        callbackInstance(tmsg, (int)color, (int)strlen(tmsg));
}
//-------------------------------------------------------------------

//Create a callback delegate
void RegisterDebugCallback(FuncCallBack cb) {
    callbackInstance = cb;
}

Usage from C++:

Debug::Log("Hellow Red", Color::Red);
Debug::Log("Hellow Green", Color::Green);
Debug::Log("Hellow Blue", Color::Blue);
Debug::Log("Hellow Black", Color::Black);
Debug::Log("Hellow White", Color::White);
Debug::Log("Hellow Yellow", Color::Yellow);
Debug::Log("Hellow Orange", Color::Orange);

Debug::Log(true, Color::Black);
Debug::Log(false, Color::Red);

Output from the Editor:

enter image description here

Now, you can easily implement Debug.LogWarning and Debug.LogError.

like image 197
Programmer Avatar answered Oct 12 '22 23:10

Programmer