Use Debug.Log from C++

前端 未结 1 1669
半阙折子戏
半阙折子戏 2020-12-05 15:19

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 d

相关标签:
1条回答
  • 2020-12-05 15:43

    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:

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

    0 讨论(0)
提交回复
热议问题