从C++使用Debug.Log

gv8xihay  于 2023-07-01  发布在  其他
关注(0)|答案(3)|浏览(122)

在Unity中制作C插件时,使用Debug.Log来快速查看变量值更容易,但该功能仅在C#端可用。这使得调试C插件非常困难,因为Unity的调试器不支持它。std::cout不是选项,因为它不会显示在编辑器中。
我查看了位于<UnityInstallationDirecory>\Editor\Data\PluginAPI的Unity C++ API,但没有找到任何关于在API中登录的内容。
关于如何在C++的编辑器日志中显示,有什么建议吗?

bt1cpqcv

bt1cpqcv1#

这可以通过回调函数来实现。发送一个指向函数的指针,从C#到C将其存储在临时变量中。将Debug.Log放入回调函数中,并允许它以指针(IntPtr)的形式接收字符串。
当从C
调用此函数时,将IntPtr转换为字符串Marshal.PtrToStringAnsi
要使其在iOS上工作,您必须在回调函数上使用MonoPInvokeCallback属性。

C#(附加到一个空的游戏对象):

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;
}

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);

编辑器输出

现在,您可以轻松实现Debug.LogWarningDebug.LogError

9jyewag0

9jyewag02#

这里有一个简单的解决方案,使用自动编组(从stringchar*)。

C++(DebugLogPlugin.cpp)

// The callback signature (shared by Unity C#)`enter code here`
using DebugLogCallback = void(const char*);

// Storage for the pointer to the Unity C# callback
static DebugLogCallback s_debugLogCallback = nullptr;

// Register the callback (called from Unity C#)
void RegisterDebugLog(DebugLogCallback callback)
{
    s_debugLogCallback = callback;
}

// Use from C++ to log the message to Unity C#
void DebugLog(const char* message)
{
    s_debugLogCallback(message);
}

// Usage example
DebugLog("Hello World");

C#(DebugLogBehaviour.cs)

// The callback signature (shared by C++). string is marshalled as const char* automatically
public delegate void DebugLogCallback(string message);

// Import our C++ register function
[DllImport("DebugLogPlugin")]
public static extern void RegisterDebugLog(DebugLogCallback callback);

// MonoBehaviour to load our plugin and register the callback
public class DebugLogBehaviour : MonoBehaviour
{
    void OnEnable()
    {
        // Call our C++ function to register the callback.
        RegisterDebugLog(DebugLog);
    }
    
    [MonoPInvokeCallback]
    static void DebugLog(string message)
    {
        Debug.Log(message);
    }
}
dxpyg8gm

dxpyg8gm3#

我找到了 * 最简单的方法 * 通过Unity Native API来实现。
在本机项目中

  • 请在%UNITY_LOCATION%\Editor\Data\PluginAPI中包含Unity Native API
  • 写一个代码如下
// Must include this one
#include "IUnityLog.h"

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SendDataFromUnityToLog(float t)
{
    string content = "Native log: " + to_string(t);
    const char* c_content = content.c_str();

    // Do this three function below to warp the log from unity
    UNITY_LOG(mLogger, c_content);
    UNITY_LOG_WARNING(mLogger, c_content);
    UNITY_LOG_ERROR(mLogger, c_content);
}

// This event trigger once unity load your plugin
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces * pInterfaces)
{
    mLogger = pInterfaces->Get<IUnityLog>();
    UNITY_LOG(mLogger, "Native Plugin load");
}

// This event trigger when unity unload your plugin
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
    UNITY_LOG(mLogger, "Native Plugin unload");
    mLogger = nullptr;
}

在你的团结计划中

[DllImport("NativePlugin")]
    private static extern void SendDataFromUnityToLog(float _);

    private void Start()
    {
        UnityEngine.Random.InitState(System.DateTime.Now.Second);
        float randNum = UnityEngine.Random.value;
        Debug.Log("Unity Log: " + randNum.ToString());

        // You must trigger this to trigger UnityPluginLoad load
        // and test it 
        SendDataFromUnityToLog(randNum);
    }

结果:result
在没有任何统一文档的情况下尝试花费了我很多时间。所以我写了一个enample:https://github.com/Darkgrouptw/UnityNativeLogger

相关问题