This is a high-level issue for general tracking, since it's a topic I'm sure we'll need at least some solution to, even if it's docs. Maybe we will identify specific use cases that we can split out into sub-issues to address in specific ways, but we will need some way of answering a user with the question "What do I do about this #if/#ifdef when I'm trying to use FFI?"
There are lots of potential use cases; here are a couple of concrete ones to provide a starting point:
-
I have a plugin that is 95+% shared iOS/macOS code, and I'm trying to convert it from Obj-C to FFI. The code that's not shared is behind a platform #if check. What's the right way to handle that in Dart? For now, I changed it to a Platform runtime check, but that's objectively worse: in the native version, if I accidentally try to use an iOS API in the macOS codepath, the code won't compile. In the Dart version, my IDE will happily auto-complete APIs that I can't actually use, without even a warning, and the code will crash at runtime, and only (I think?) once I hit that code. Can we do better?
-
WKWebView has the following definition:
#if TARGET_OS_IPHONE
WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0))
@interface WKWebView : UIView
#else
WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0))
@interface WKWebView : NSView
#endif
What should ffigen even create here? Is there any good option? The general case of this can get arbitrarily complicated; e.g., if the answer to the first question is that it inherits from some franken-class that is a mashup of NSView and UIView so that I can get any method I need, what happens if there's a collision between methods (e.g., each has a method with the same name but a different return type—a plausible scenario since methods called view that return the platform view type are common, for example). Or do we recommend putting everything behind a more FFI-friendly native facade in a case like this?
(#1469 touched on this slightly, but was specifically about the generation of code that did not compile, rather than the overall use case.)
This is a high-level issue for general tracking, since it's a topic I'm sure we'll need at least some solution to, even if it's docs. Maybe we will identify specific use cases that we can split out into sub-issues to address in specific ways, but we will need some way of answering a user with the question "What do I do about this
#if/#ifdefwhen I'm trying to use FFI?"There are lots of potential use cases; here are a couple of concrete ones to provide a starting point:
I have a plugin that is 95+% shared iOS/macOS code, and I'm trying to convert it from Obj-C to FFI. The code that's not shared is behind a platform
#ifcheck. What's the right way to handle that in Dart? For now, I changed it to aPlatformruntime check, but that's objectively worse: in the native version, if I accidentally try to use an iOS API in the macOS codepath, the code won't compile. In the Dart version, my IDE will happily auto-complete APIs that I can't actually use, without even a warning, and the code will crash at runtime, and only (I think?) once I hit that code. Can we do better?WKWebViewhas the following definition:What should
ffigeneven create here? Is there any good option? The general case of this can get arbitrarily complicated; e.g., if the answer to the first question is that it inherits from some franken-class that is a mashup ofNSViewandUIViewso that I can get any method I need, what happens if there's a collision between methods (e.g., each has a method with the same name but a different return type—a plausible scenario since methods calledviewthat return the platform view type are common, for example). Or do we recommend putting everything behind a more FFI-friendly native facade in a case like this?(#1469 touched on this slightly, but was specifically about the generation of code that did not compile, rather than the overall use case.)