如何 P/Invoke os_log?

Jac*_*jek 2 c# macos pinvoke .net-core oslog

在 .NET Core 控制台应用程序中从 C# 调用 MacOS 的 os_log 的语法应该是什么

基于
https://developer.apple.com/documentation/os/os_log

如何将 iOS OSLog 与 Xamarin 一起使用?

https://opensource.apple.com/source/xnu/xnu-4903.221.2/libkern/os/log.h.auto.html
我期待这样的事情:

using System.Runtime.InteropServices;

namespace Foo 
{
 class Program
 {
  [DllImport("__Internal", EntryPoint = "os_log_create")]
  private static extern IntPtr os_log_create(string subsystem, string category);

  [DllImport("__Internal", EntryPoint = "os_log")]
  private static extern void os_log(IntPtr log, string format, string message);

  static void Main(string[] args)
  {  
   IntPtr log = os_log_create("some.bundle.id", "SomeCategory");
   os_log(log, "%s", "Test!");
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试在我的 Mac 上运行它时,我得到一个System.DllNotFoundExceptionUnable to load shared library '__Internal' or one of its dependencies....

对此问题的任何帮助或 C# 和 MacOS 之间的 P/Invoke 都会非常有帮助,谢谢!

Ste*_*cht 6

宏 os_log

与 os_log_create 函数相比,os_log 是一个宏,正如评论中已经提到的。

所以如果你用C写:

os_log(log, "%{public}s", "Test!");
Run Code Online (Sandbox Code Playgroud)

它最终会调用一个名为 _os_log_impl 的函数,但它的第一个参数将是一个指针 __dso_handle,我们无法从托管端访问它。

可能的解决方案

但您不必离开 Apple 的新日志系统。一种可能性是创建一个动态库,该库提供可从托管 C# 代码轻松调用的已定义 API。

如何在 Xcode 中创建动态库

在 Xcode 中创建动态库很容易:

  • 在 XCode 中选择 <File/New Project>

  • macOS部分选择模板

  • 使用类型动态

最小示例

我们自己的Logging库的最小 .c 示例可能如下所示:

 #include <os/log.h>

 extern void Log(os_log_t log, char *message) {
     os_log(log, "%{public}s", message);
 }
Run Code Online (Sandbox Code Playgroud)

从 .Net 调用

我拿了你的来源,只是稍微修改了它:

using System;
using System.Runtime.InteropServices;

namespace Foo 
{
    class Program
    {
        [DllImport("System", EntryPoint = "os_log_create")]
        private static extern IntPtr os_log_create(string subsystem, string category);

        [DllImport("Logging", EntryPoint = "Log")]
        private static extern void Log(IntPtr log, string msg);

        static void Main(string[] args)
        {  
            IntPtr log = os_log_create("some.bundle.id", "SomeCategory");
            Log(log, "Test!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用 Xcode 创建的动态库的名称为Logging。我们在 C 中创建的日志函数在这里命名为Log

当然,您可以随心所欲地设计 API,这应该是一个尽可能接近问题的最小示例。

控制台实用程序中的输出

Console 实用程序中的输出(如果您过滤some.bundle.id)将如下所示:

控制台实用程序中的输出

  • 如果我在一个简短的截屏视频中展示它可能会更容易:创建 dylib 和测试运行 3 分钟:https://www.software7.biz/iertzhghbvldhzh/CreateLoggingLib.mp4 (2认同)