gpt4 book ai didi

c# - 如何从 .Net Core 应用程序 PInvoke AppKit 方法?

转载 作者:行者123 更新时间:2023-12-03 19:50:41 28 4
gpt4 key购买 nike

在 Mac OS 上的 .Net Core 上运行时,是否可以使用 PInvoke 调用 AppKit 方法?具体来说,我想使用 NSWorkspace.Recycle 方法。

根据documentation MacOS 支持 PInvoke,只是不清楚如何使用它与 AppKit 等框架进行交互。

最佳答案

PInvoke 仅适用于 C 方法,但由于 Objective C 运行时基于 C 方法,我们可以使用它们。 Xamarin 将提供所有必要的设置和便利方法,但这是可能的。请注意,此示例使用不安全代码,因此需要在 csproj 文件中设置以下属性:

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

下面是完整代码,注意 objc_msgSend需要使用正确的签名多次导入。在 C 中,这可以通过将其转换为具有正确签名的不同函数指针来完成。框架也需要通过完整路径导入,因为CoreCLR没有框架的探测逻辑,它会搜索 lib{sth}.dylib反而。
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace NSWorkspaceExample
{
public class Program
{
static void Main(string[] args)
{
var testFile = Path.Combine(Directory.GetCurrentDirectory(), "test.txt");
File.WriteAllText(testFile, "example file content");

var cfstrTestFile = CreateCFString(testFile);
var nsURL = objc_getClass("NSURL");
var fileUrl = objc_msgSend_retIntPtr_IntPtr(nsURL, GetSelector("fileURLWithPath:"), cfstrTestFile);
CFRelease(cfstrTestFile);

var urlArray = CreateCFArray(new IntPtr[] {fileUrl});

var nsWorkspace = objc_getClass("NSWorkspace");
var sharedWorkspace = objc_msgSend_retIntPtr(nsWorkspace, GetSelector("sharedWorkspace"));

objc_msgSend_retVoid_IntPtr_IntPtr(sharedWorkspace, GetSelector("recycleURLs:completionHandler:"), urlArray, IntPtr.Zero);

CFRelease(urlArray);
CFRelease(fileUrl);
CFRelease(sharedWorkspace);

// sleep since we didn't go through the troubles of creating a block object as a callback
Thread.Sleep(1000);
}

public static IntPtr GetSelector(string name)
{
IntPtr cfstrSelector = CreateCFString(name);
IntPtr selector = NSSelectorFromString(cfstrSelector);
CFRelease(cfstrSelector);
return selector;
}

private const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation";
private const string AppKitFramework = "/System/Library/Frameworks/AppKit.framework/AppKit";

public unsafe static IntPtr CreateCFString(string aString)
{
var bytes = Encoding.Unicode.GetBytes(aString);
fixed (byte* b = bytes) {
var cfStr = CFStringCreateWithBytes(IntPtr.Zero, (IntPtr)b, bytes.Length, CFStringEncoding.UTF16, false);
return cfStr;
}
}

// warning: this doesn't call retain/release on the elements in the array
public unsafe static IntPtr CreateCFArray(IntPtr[] objectes)
{
fixed(IntPtr* vals = objectes) {
return CFArrayCreate(IntPtr.Zero, (IntPtr)vals, objectes.Length, IntPtr.Zero);
}
}

[DllImport(FoundationFramework)]
public static extern IntPtr CFStringCreateWithBytes(IntPtr allocator, IntPtr buffer, long bufferLength, CFStringEncoding encoding, bool isExternalRepresentation);

[DllImport(FoundationFramework)]
public static extern IntPtr CFArrayCreate(IntPtr allocator, IntPtr values, long numValues, IntPtr callbackStruct);

[DllImport(FoundationFramework)]
public static extern void CFRetain(IntPtr handle);

[DllImport(FoundationFramework)]
public static extern void CFRelease(IntPtr handle);

[DllImport(AppKitFramework, CharSet = CharSet.Ansi)]
public static extern IntPtr objc_getClass(string name);

[DllImport(AppKitFramework)]
public static extern IntPtr NSSelectorFromString(IntPtr cfstr);

[DllImport(FoundationFramework, EntryPoint="objc_msgSend")]
public static extern IntPtr objc_msgSend_retIntPtr(IntPtr target, IntPtr selector);

[DllImport(FoundationFramework, EntryPoint="objc_msgSend")]
public static extern void objc_msgSend_retVoid_IntPtr_IntPtr(IntPtr target, IntPtr selector, IntPtr param1, IntPtr param2);

[DllImport(FoundationFramework, EntryPoint="objc_msgSend")]
public static extern IntPtr objc_msgSend_retIntPtr_IntPtr(IntPtr target, IntPtr selector, IntPtr param);

[DllImport(FoundationFramework, EntryPoint="objc_msgSend")]
public static extern void objc_msgSend_retVoid(IntPtr target, IntPtr selector);

public enum CFStringEncoding : uint
{
UTF16 = 0x0100,
UTF16BE = 0x10000100,
UTF16LE = 0x14000100,
ASCII = 0x0600
}
}
}

关于c# - 如何从 .Net Core 应用程序 PInvoke AppKit 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44665544/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com