Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS Silicon error: "NSWindow should only be instantiated on the main thread!" #19

Closed
TomTom101 opened this issue Dec 11, 2023 · 2 comments
Labels
status: investigate Research or design is required type: bug Something isn't working

Comments

@TomTom101
Copy link

Same problem as #17 (at least on an ARM based Mac, the library is named libopencv_ffi.dylib, so the first change needed is this:

String _getPath() {
  if (Platform.isWindows) {
    return "opencv_ffi.dll";
  } else if (Platform.isMacOS) {
    return "libopencv_ffi.dylib";
  } else if (Platform.isLinux) {
    return "libopencv_ffi.so";
  } else {
    throw UnsupportedError("Unsupported platform");
  }
}

Second issue here is that Dart does not seem to care about the LD_LIBRARY_PATH. I have it set, confirmed by echo $LD_LIBRARY_PATH, but it still not found. The given path is not searched for the lib.

I then symlinked the lib to the current directory, where it is found and end up with this error:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSWindow should only be instantiated on the main thread!'
*** First throw call stack:
(
        0   CoreFoundation                      0x0000000186fc2800 __exceptionPreprocess + 176
        1   libobjc.A.dylib                     0x0000000186ab9eb4 objc_exception_throw + 60
        2   CoreFoundation                      0x0000000186fe7b4c _CFBundleGetValueForInfoKey + 0
        3   AppKit                              0x000000018a737538 -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 188
        4   AppKit                              0x000000018a737470 -[NSWindow initWithContentRect:styleMask:backing:defer:] + 48
        5   AppKit                              0x000000018a992b84 -[NSWindow initWithContentRect:styleMask:backing:defer:screen:] + 24
        6   libopencv_highgui.4.8.0.dylib       0x00000001077a1454 cvNamedWindow + 436
        7   libopencv_highgui.4.8.0.dylib       0x00000001077a0eac cvShowImage + 88
        8   libopencv_highgui.4.8.0.dylib       0x000000010779ad58 _ZN2cv6imshowERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKNS_11_InputArrayE + 1376
        9   libopencv_ffi.dylib                 0x0000000106c6839c imshow + 68
        10  ???                                 0x0000000106c87a28 0x0 + 4408769064
        11  ???                                 0x000000010e033134 0x0 + 4530057524
        12  ???                                 0x000000010e032bec 0x0 + 4530056172
        13  ???                                 0x000000010e031fc0 0x0 + 4530053056
        14  ???                                 0x000000010e02e444 0x0 + 4530037828
        15  ???                                 0x000000010e02e27c 0x0 + 4530037372
        16  ???                                 0x000000010e02e158 0x0 + 4530037080
        17  ???                                 0x000000010e02c9a8 0x0 + 4530031016
        18  ???                                 0x000000010e02c600 0x0 + 4530030080
        19  ???                                 0x000000010e02b0e8 0x0 + 4530024680
        20  ???                                 0x0000000106c83404 0x0 + 4408751108
        21  dart                                0x00000001048fd83c dart + 1464380
        22  dart                                0x00000001048ff2f4 dart + 1471220
        23  dart                                0x000000010491cbe4 dart + 1592292
        24  dart                                0x000000010493f830 dart + 1734704
        25  dart                                0x000000010493fe5c dart + 1736284
        26  dart                                0x0000000104a47ef4 dart + 2817780
        27  dart                                0x0000000104a4816c dart + 2818412
        28  dart                                0x00000001049d24a0 dart + 2335904
        29  libsystem_pthread.dylib             0x0000000186e71034 _pthread_start + 136
        30  libsystem_pthread.dylib             0x0000000186e6be3c thread_start + 8
)
libc++abi: terminating due to uncaught exception of type NSException
@Levi-Lesches
Copy link
Owner

Second issue here is that Dart does not seem to care about the LD_LIBRARY_PATH. I have it set, confirmed by echo $LD_LIBRARY_PATH, but it still not found. The given path is not searched for the lib.

Yep, I found that too. Have not found a proper solution to this but once the Native Assets feature makes it to the stable Dart version, this won't be an issue anymore.

From your stack trace:

libopencv_ffi.dylib                 0x0000000106c6839c imshow + 68

Seems like imshow (or at least, our usage of it) isn't playing nicely with the way Apple expects it to work. Here's the C++ side:

FFI_PLUGIN_EXPORT void imshow(Mat* image) {
  cv::Mat* cvImage = reinterpret_cast<cv::Mat*>(image);
  cv::imshow("Wrapper", *cvImage);
  cv::waitKey(1);
}

and here's the Dart side:

  void showFrame() {
    if (!_read()) throw CameraReadException();
    nativeLib.imshow(_image);
  }

Are you using isolates by any chance? If not, it could be that Dart's FFI mechanisms use threads somehow. I can ask around, but I don't know what's causing the issue nor do I have a Mac to debug it.

If you know your way around C/C++, may I suggest:

  • Writing your own script to #include src/opencv_ffi.h
  • Using VideoCapture_read and imshow in your C/C++ code
  • building OpenCV, opencv_ffi, and your code to try to reproduce the error

@Levi-Lesches Levi-Lesches added status: investigate Research or design is required type: bug Something isn't working labels Dec 12, 2023
@Levi-Lesches
Copy link
Owner

Levi-Lesches commented Dec 13, 2023

Just ran this through @mraleph, seems this is an issue with Dart's FFI. Not sure what your next move should be, sorry, but for me, I found it useful to avoid imshow/showFrame altogether and stream the bytes directly to some other I/O, like Flutter's Image widget, or saving them to a file. After all, you can't control much of the OpenCV window, and I mostly just included it as a debug feature.

Here is an issue whose last comment explains the difficulties in this. If you feel imshow() is worth it to you and you understand what they're saying and how to go about it, feel free to try that solution. If not, it doesn't look like this will be fixed anytime soon (although this other issue notes that this should be solved for Flutter soon, it's just native Dart that won't work).

Closing as this is out of scope for this package, but feel free to subscribe or post your use-case to the above issues.

@Levi-Lesches Levi-Lesches closed this as not planned Won't fix, can't repro, duplicate, stale Dec 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: investigate Research or design is required type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants