objc2 icon indicating copy to clipboard operation
objc2 copied to clipboard

Add network framework

Open pronebird opened this issue 3 months ago • 3 comments

This is a boilerplate PR for adding bindings for network framework.

objc-network

  • Add nw_object macros to create network (NW) objects
  • Introduce NWRetained type. Same as Retained but calls into nw_retain and nw_release.
  • Add placeholders for all NW types
  • Add sample wrapper for Path and PathMonitor types raising some questions on how we should handle pointers, bindings.
  • Generated Network framework bindings with Xcode 16.2 (I don't have newer): https://github.com/madsmtm/objc2-generated/commit/3c04ac72420fbc460f81be123267ece45c12c382

Changes to header-translator

  • Recognize nw_ types in order to use NWRetained instead of Retained
  • Handle NW_RETURNS_RETAINED, NW_NOESCAPE, NW_SWIFT_DISABLE_ASYNC, NW_ENUM

Questions

For what it's worth, it compiles. However I have raised some questions in the code, maybe you could help me to fix the missing bits. Of course in general I'd like to know if the direction I took is the one that you envisioned for network framework and other frameworks too.

Use of self in wrapper types

A lot of nw_* methods are generated with network objects passed as NonNull<T>. This is handled this way in header-translator and I had copied this bit verbatim assuming there is no difference with dispatch2. However It feels weird that i need to use NonNull::from(self), i.e:

pub fn prohibit_interface_type(&mut self, interface_type: InterfaceType) {
  unsafe {
    nw_path_monitor_prohibit_interface_type(
      // fixme: should be able to use &PathMonitor?
      NonNull::from(self),
      interface_type,
    );
  }
}

What woudl be the right approach?

Arrays generated as ArrayUnknownABI

A 6-char C-array was generated as ArrayUnknownABI. What should I specify and where to generate a normal C array? Currently skipping the symbol and providing it manually via lib.rs:

#[allow(non_camel_case_types)]
pub type nw_ethernet_address_t = [core::ffi::c_uchar; 6];

Type-aliases for generated types

I have to define type-aliases in lib.rs since I subtitute nw_*_t types with my own structs, for example:

#[allow(non_camel_case_types)]
type nw_advertise_descriptor_t = AdvertiseDescriptor;

Should I type-alias it wrapped in NWRetained, i.e NWRetained<AdvertiseDescriptor>?

pronebird avatar Sep 24 '25 09:09 pronebird

I'd like the prefix NW, e.g. nw_path_t -> NWPath like Swift does it, but that's already used by NetworkExtension

From what I can see in the docs, when searching for nw in the bottom left bar, almost everything that comes up is either some kind of Obj-C class around a Network-like type that is now deprecated in favor of the Network type or something directly from Network itself. Furthermore, these constitute a minority compared to the rest that starts with NE, as one would expect more. It would seem like these wrappers should have been directly in Network, hence the naming, but were made available from NetworkExtension instead for some obscure reasons.

Considering this, I think using the NW prefix here would be preferable in order to remain consistent with how other frameworks have their items named and how this one already has the nw_ prefix in most items, if it's technically feasible. It would introduce some slight confusion, but it would effectively represent what is exposed in a transparent manner, i.e. the confusion is more on them than on us. Also, there shouldn't be too much of a risk of clashing, except in downstream imports that can always be adapted, right?

PaulDance avatar Sep 26 '25 17:09 PaulDance

I'd like the prefix NW, e.g. nw_path_t -> NWPath like Swift does it, but that's already used by NetworkExtension

From what I can see in the docs, when searching for nw in the bottom left bar, almost everything that comes up is either some kind of Obj-C class around a Network-like type that is now deprecated in favor of the Network type or something directly from Network itself. Furthermore, these constitute a minority compared to the rest that starts with NE, as one would expect more. It would seem like these wrappers should have been directly in Network, hence the naming, but were made available from NetworkExtension instead for some obscure reasons.

Considering this, I think using the NW prefix here would be preferable in order to remain consistent with how other frameworks have their items named and how this one already has the nw_ prefix in most items, if it's technically feasible. It would introduce some slight confusion, but it would effectively represent what is exposed in a transparent manner, i.e. the confusion is more on them than on us. Also, there shouldn't be too much of a risk of clashing, except in downstream imports that can always be adapted, right?

I think that class prefix is only relevant for Swift/Objc due semantics of how modules work in those languages. Rust does not have this problem, hence a few deprecated types from NetworkExtension that carry the same name shouldn't matter. On the other side I don't know why the prefix is even used in Rust bindings, it looks ugly. Personally I don't care all that much for prefix. Whichever way we go, my primary objective is to be able to use network framework from Rust :)

pronebird avatar Sep 28 '25 09:09 pronebird

Alright so I kinda forced header translator to produce something decent. We might need to separate cf_fn_name() from NW because I have seen some odd side effects. My patch is quite terrible as it is right now, it needs a decent refactor.

Latest bindings: https://github.com/pronebird/objc2-generated/blob/network-bindings/Network/mod.rs

pronebird avatar Sep 28 '25 16:09 pronebird