madsmtm / objc2

Bindings to Apple's frameworks in Rust
https://docs.rs/objc2/
MIT License
371 stars 39 forks source link

Unable to get basic Vision function working #664

Open jbham opened 2 weeks ago

jbham commented 2 weeks ago

After banging my head for over a day and not getting anywhere, I am coming here to request for help.

I am trying to get a basic OCR running. However, it doesn't seems to work. Below is what I have tried already.

My code:

let image_data = std::fs::read(path).unwrap();

// Create Request Handler:
let arg1 = objc2_vision::VNImageRequestHandler::alloc();
let arg2 = NSData::with_bytes(&image_data);
let arg3 = NSDictionary::new();

let request_handler = unsafe { objc2_vision::VNImageRequestHandler::initWithData_options(arg1, &arg2, &arg3) };

// Create new request
let req_arg1 = objc2_vision::VNRecognizeTextRequest::alloc();
let a2 = unsafe { objc2_vision::VNRequest::new() };
let req_arg2 = unsafe { objc2_vision::VNRequest::completionHandler(&a2) };

let requests = unsafe { objc2_vision::VNRecognizeTextRequest::initWithCompletionHandler(req_arg1, req_arg2) };

let mut def = NSArray::new();
unsafe { request_handler.performRequests_error(&def) }.unwrap();
let observations = unsafe { requests.results() };

I know (I think) my issue is in the way I am preparing my req_arg2 argument since thats where most of the magic will be happening. But, I can't get it to work :(

I tried to create a block with closure in different ways but i didn't get anywhere.

If I can get some help then that would be really appreciated!

madsmtm commented 1 week ago

I haven't used the Vision framework myself, but my guess is that you need to create the actual handler block yourself using the block2 crate?

Something like (very untested):

let completion_handler = block2::RcBlock::new(|request: NonNull<VNRequest>, error: *mut NSError| unsafe {
    dbg!(request.as_ref());
    dbg!(error.as_ref());
});
let block_ptr = &completion_handler as &Block<_> as *const Block<_> as *mut Block<_>;

let request = unsafe {
    objc2_vision::VNRecognizeTextRequest::initWithCompletionHandler(
        objc2_vision::VNRecognizeTextRequest::alloc(),
        block_ptr,
    )
};

let mut def = <NSMutableArray<VNRequest>>::new();
def.push(&request);
unsafe { request_handler.performRequests_error(&def) }.unwrap();
let observations = unsafe { request.results() };
madsmtm commented 1 week ago

(Part of this is made easier in the yet unreleased version of block2, which includes a .as_ptr() to make the conversion to *mut Block<_> easier).