Good evening, I'm trying to access ScreenCaptureKit from Maui MacCatalyst. I believe I have set everything up correctly, however, I continue to get the same issue. I was hoping someone could give me some insight into what I am doing wrong.
My error:
7>Xamarin.Shared.Sdk.targets(1643,3): Error : clang++ exited with code 1:
Undefined symbols for architecture arm64:
"_OBJCCLASS$_SCStream", referenced from:
"_OBJC_CLASS_$_SCStreamOutput", referenced from:
"_OBJC_CLASS_$_ScreenCapture", referenced from:
ld: symbol(s) not found for architecture arm64
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
I created my framework in XCode with one class to test the initial implementation.
`import ScreenCaptureKit
@objcMembers
@objc(ScreenCapture) public class ScreenCapture: NSObject, SCStreamDelegate, SCStreamOutput {
private static var captureCompletion: ((NSData?) -> Void)?
private var stream: SCStream?
@objc(captureFullScreenWithCompletion:) public static func captureFullScreen(completion: @escaping (NSData?) -> Void) {
// Set the completion handler for later use in the delegate method
captureCompletion = completion
let screenCapture = ScreenCapture()
Task {
do {
// Access the main display for screen capture
let shareableContent = try await SCShareableContent.current
guard let mainDisplay = shareableContent.displays.first else {
completion(nil)
return
}
// Set up the content filter and stream configuration
let filter = SCContentFilter(display: mainDisplay, excludingWindows: [])
let config = SCStreamConfiguration()
config.width = Int(mainDisplay.width)
config.height = Int(mainDisplay.height)
config.pixelFormat = kCVPixelFormatType_32BGRA
// Initialize the stream with the content filter, configuration, and delegate
screenCapture.stream = SCStream(filter: filter, configuration: config, delegate: screenCapture)
// Set the ScreenCapture class as the output
try screenCapture.stream?.addStreamOutput(screenCapture, type: .screen, sampleHandlerQueue: .main)
// Start the capture session
try await screenCapture.stream?.startCapture()
} catch {
print("Failed to start screen capture: \(error)")
completion(nil)
}
}
}
// SCStreamOutput delegate method to handle the frame output
@objc public func stream(_ stream: SCStream, didOutput sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType){
guard type == .screen,
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
ScreenCapture.captureCompletion?(nil)
ScreenCapture.captureCompletion = nil
stream.stopCapture { _ in }
return
}
// Convert CVPixelBuffer to NSData directly
let ciImage = CIImage(cvPixelBuffer: imageBuffer)
// Render the CIImage to PNG data using Core Image
let context = CIContext(options: nil)
if let pngData = context.pngRepresentation(of: ciImage, format: .BGRA8, colorSpace: CGColorSpaceCreateDeviceRGB()) {
ScreenCapture.captureCompletion?(pngData as NSData)
} else {
ScreenCapture.captureCompletion?(nil)
}
// Stop the stream after capturing one frame
ScreenCapture.captureCompletion = nil
stream.stopCapture { _ in }
}
// SCStreamDelegate method to handle any errors during the streaming session
@objc public func stream(_ stream: SCStream, didStopWithError error: Error) {
print("Stream stopped with error: \(error)")
ScreenCapture.captureCompletion?(nil)
ScreenCapture.captureCompletion = nil
}
}
`
I created the project for binding with the template per the docs. I am also referencing my local xcodeproj for the framework:
`ScreenCaptureFrameworkScreenCapturetrueFrameworktrue`
I created the ApiDefinitions.cs file myself, and am really struggling to get this to work.
`#nullable enable
using System;
using Foundation;
using ObjCRuntime;
using CoreMedia;
using CoreFoundation; // Add this for DispatchQueue
namespace Seea.NativeBinding
{
[BaseType(typeof(NSObject))]
interface ScreenCapture
{
[Static]
[Export("captureFullScreenWithCompletion:")]
void CaptureFullScreenWithCompletion(Action completion);
[Export("stream:didOutput:of:")]
void DidOutput(SCStream stream, CMSampleBuffer sampleBuffer, SCStreamOutputType type);
[Export("stream:didStopWithError:")]
void DidStopWithError(SCStream stream, NSError error);
}
[BaseType(typeof(NSObject))]
interface SCStream
{
[Export("startCaptureWithCompletionHandler:")]
void StartCapture([NullAllowed] Action completionHandler);
[Export("stopCaptureWithCompletionHandler:")]
void StopCapture([NullAllowed] Action completionHandler);
[Export("addStreamOutput:type:sampleHandlerQueue:error:")]
bool AddStreamOutput(SCStreamOutput output, SCStreamOutputType type, [NullAllowed] DispatchQueue sampleHandlerQueue, out NSError error);
[Export("removeStreamOutput:type:error:")]
bool RemoveStreamOutput(SCStreamOutput output, SCStreamOutputType type, out NSError error);
}
[BaseType(typeof(NSObject))]
interface SCStreamOutput
{
// This method handles the output of a sample buffer in the stream.
[Abstract]
[Export("stream:didOutput:of:")]
void DidOutput(SCStream stream, CMSampleBuffer sampleBuffer, SCStreamOutputType type);
}
}`
I know I am probably doing this wrong somewhere, but I could really use some insight if anyone has had this issue besides myself.
Thanks!
Good evening, I'm trying to access ScreenCaptureKit from Maui MacCatalyst. I believe I have set everything up correctly, however, I continue to get the same issue. I was hoping someone could give me some insight into what I am doing wrong.
My error:
7>Xamarin.Shared.Sdk.targets(1643,3): Error : clang++ exited with code 1: Undefined symbols for architecture arm64: "_OBJCCLASS$_SCStream", referenced from: