如何P/Invokeos_log?
How to P/Invoke os_log?
在 .NET Core 控制台应用程序中从 C# 调用 MacOS' os_log 的语法应该是什么?
基于
https://developer.apple.com/documentation/os/os_log
和
How to use iOS OSLog with 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!");
}
}
}
但是,当我尝试在我的 Mac 上 运行 时,我得到一个 System.DllNotFoundException
,上面写着 Unable to load shared library '__Internal' or one of its dependencies...
。
任何有关此问题的帮助或 C# 和 MacOS 之间的 P/Invoke 都会非常有帮助,谢谢!
宏os_log
与os_log_create函数相反,os_log是一个宏,正如评论中已经提到的那样。
所以如果你用 C 写:
os_log(log, "%{public}s", "Test!");
它最终会调用一个名为 _os_log_impl 的函数,但它的第一个参数将是一个指针 __dso_handle,我们无法从托管端访问它。
可能的解决方案
但是您不必离不开 Apple 的新日志系统。一种可能性是创建一个动态库,该库提供已定义的 API,可以从托管 C# 代码轻松调用。
如何在Xcode
中创建动态库
在Xcode中创建动态库很容易:
在XCode
在 macOS 部分选择 Library 模板
使用类型动态
最小示例
我们自己的 Logging 库的最小 .c 示例可能如下所示:
#include <os/log.h>
extern void Log(os_log_t log, char *message) {
os_log(log, "%{public}s", message);
}
从 .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!");
}
}
}
使用 Xcode 创建的动态库名称为 Logging。我们在 C 中创建的日志记录函数在此处命名为 Log。
当然你可以把API设计成你想要的舒适度,这应该是一个尽可能接近问题的最小例子。
控制台实用程序中的输出
控制台实用程序中的输出(如果您筛选 some.bundle.id)将如下所示:
在 .NET Core 控制台应用程序中从 C# 调用 MacOS' os_log 的语法应该是什么?
基于
https://developer.apple.com/documentation/os/os_log
和
How to use iOS OSLog with 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!");
}
}
}
但是,当我尝试在我的 Mac 上 运行 时,我得到一个 System.DllNotFoundException
,上面写着 Unable to load shared library '__Internal' or one of its dependencies...
。
任何有关此问题的帮助或 C# 和 MacOS 之间的 P/Invoke 都会非常有帮助,谢谢!
宏os_log
与os_log_create函数相反,os_log是一个宏,正如评论中已经提到的那样。
所以如果你用 C 写:
os_log(log, "%{public}s", "Test!");
它最终会调用一个名为 _os_log_impl 的函数,但它的第一个参数将是一个指针 __dso_handle,我们无法从托管端访问它。
可能的解决方案
但是您不必离不开 Apple 的新日志系统。一种可能性是创建一个动态库,该库提供已定义的 API,可以从托管 C# 代码轻松调用。
如何在Xcode
中创建动态库在Xcode中创建动态库很容易:
在XCode
在 macOS 部分选择 Library 模板
使用类型动态
最小示例
我们自己的 Logging 库的最小 .c 示例可能如下所示:
#include <os/log.h>
extern void Log(os_log_t log, char *message) {
os_log(log, "%{public}s", message);
}
从 .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!");
}
}
}
使用 Xcode 创建的动态库名称为 Logging。我们在 C 中创建的日志记录函数在此处命名为 Log。
当然你可以把API设计成你想要的舒适度,这应该是一个尽可能接近问题的最小例子。
控制台实用程序中的输出
控制台实用程序中的输出(如果您筛选 some.bundle.id)将如下所示: