Skip to content

test: Try importing NitroTestExternal's Swift header inside NitroTest's C++ code#1154

Draft
mrousavy wants to merge 3 commits intomainfrom
experiment/spm
Draft

test: Try importing NitroTestExternal's Swift header inside NitroTest's C++ code#1154
mrousavy wants to merge 3 commits intomainfrom
experiment/spm

Conversation

@mrousavy
Copy link
Owner

@mrousavy mrousavy commented Jan 14, 2026

Problem

What I want to do is to allow extending a type from another module inside the user's Nitro Module.
Just passing a type from another module as a parameter, or returning it, works fine, but once we want to set up inheritance we need to know the type before including our generated Swift header, and that's where things break because the Swift compiler generates code like this in *-Swift.h:

class SWIFT_SYMBOL("s:13Second06FirstC") Second : public FirstPod::First {
public:
  using First::First;
  using First::operator=;
  static SWIFT_INLINE_THUNK Second init() SWIFT_SYMBOL("s:13Second06FirstCACycfc");
protected:
  SWIFT_INLINE_THUNK Second(void * _Nonnull ptr) noexcept : First(ptr) {}
private:
  friend class _impl::_impl_Second;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++17-extensions"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreserved-identifier"
  typedef char $s13Second06FirstCD;
  static inline constexpr $s13Second06FirstCD __swift_mangled_name = 0;
#pragma clang diagnostic pop
#pragma clang diagnostic pop
};

As you can see, FirstPod::First is used here (and can't be forward-declared), so we must import it (*-Swift.h doesn't do this by itself, so we have to import/define it before importing our *-Swift.h).
But here's where the problems start, because importing the external generated FirstPod-Swift.h header in our module is not as easy as it sounds.

Findings

Here's my findings after trying to import a Swift generated type inside another module's C++ code (as title says):

  1. The -Swift.h header is private to the specific module. So NitroTest-Swift.h can only be imported in NitroTest , and NitroTestExternal-Swift.h in NitroTestExternal. You cannot import NitroTestExternal-Swift.h inside the NitroTest module. To fix this, we can enable use_frameworks! in the Podfile (we can maybe guard this with #if defined(FRAMEWORKS), not yet tested).
  2. I tried playing around with a subspec in the Pod called Cxx which only exposes the headers, to avoid recursively importing the -Swift.h header.
  3. Once you figure out the frameworks and import logic (which I did as of a8009fa), you run into the actual problem: the Swift compiler definitions are now duplicated for some of our types. Specifically the type that we want to share; std::shared_ptr< HybridSomeExternalObjectSpec> - this one is defined in NitroTest-Swift.h and NitroTestExternal-Swift.h. How do we fix that? No idea.
    xcode screenshot of errors

Side Thoughts

The duplicate definitions are coming from what the Swift compiler emits as public API surface, and since both my Swift classes have public functions accepting or returning C++ types, those are part of the public API. And since the same type is used in two separate modules, the -Swift.h header redefines it, which breaks when I try to include both -Swift.h headers in a single module (when not doing that it's fine as it's separate modules).

I currently only see two solutions:

  1. Don't use any C++ types in Swift at all, and only use Swift types from C++ (That's the SwiftConverter<T> thingy I kept talking about, but this is gonna be super tricky since some types are simply not supported - e.g. swift::Dictionary<...>)
  2. Add Swift compiler support to avoid redefining types and tell it to just trust that the type is going to be imported from a separate module (or have it do that automatically, e.g. forward declare and import framework) - that'll ideally require no changes from my end

@vercel
Copy link

vercel bot commented Jan 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
nitro-docs Skipped Skipped Jan 14, 2026 7:23pm

@mrousavy mrousavy changed the title test: Try importing NitroTestExternal's Swift header inside `NitroT… test: Try importing NitroTestExternal's Swift header inside NitroTest's C++ code Jan 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant