Skip to content

fix(macos): declare UIImagePNGRepresentation and UIImageJPEGRepresentation extern "C" - #3140

Open
Bron Davies (brondavies) wants to merge 1 commit into
microsoft:mainfrom
brondavies:fix/rctuiimage-extern-c
Open

Bron Davies (brondavies) wants to merge 1 commit into
microsoft:mainfrom
brondavies:fix/rctuiimage-extern-c

Conversation

@brondavies

Copy link
Copy Markdown

Summary:

Fixes #3137.

UIImagePNGRepresentation and UIImageJPEGRepresentation are defined in RCTUIImage.m (Objective-C), so their symbols are C, but RCTUIImage.h declared them without extern "C". An Objective-C++ caller then asks for C++-mangled names and fails to link on macOS (react-native-svg's RNSVGSvgView.mm, for one). They now sit in an extern "C" block, like UIImageGetScale and UIImageGetCGImageRef above them.

That on its own breaks RNTester's link: RCTImageLoader.mm kept a copy of both functions from when React-RCTImage couldn't depend on RCTUIKit (#1611). As C++ the copies had mangled names and never clashed; declared extern "C" they become duplicate symbols. React-Core depends on React-RCTUIKit now (React-Core.podspec), and RCTImageLoader.mm already sees RCTUIImage.h, so the copy is removed and the image loader uses RCTUIKit's implementation, which is the same code.

Test Plan:

  • Two files, before and after. The two RCTUIKit files and a one-line Objective-C++ caller:
    K=packages/react-native/ReactApple/Libraries/RCTUIKit
    xcrun clang -c -fobjc-arc -fmodules -I$K $K/RCTUIImage.m -o RCTUIImage.o
    xcrun clang++ -c -fobjc-arc -fmodules -I$K caller.mm -o caller.o   # calls UIImagePNGRepresentation
    xcrun clang++ caller.o RCTUIImage.o -framework AppKit
    On main the link fails with "UIImagePNGRepresentation(NSImage*)", referenced from: _main in caller.o and ld's note that _UIImagePNGRepresentation is in RCTUIImage.o, possibly missing extern "C". With this change it links.
  • RNTester-macOS (Debug, arm64, Xcode 27.1, macOS 26.6.2) builds and links. With only the header change it fails with duplicate symbol '_UIImagePNGRepresentation' (and JPEG) in RCTImageLoader.o and RCTUIImage.o; with the copy removed, nm shows one T _UIImagePNGRepresentation and one T _UIImageJPEGRepresentation in RNTester-macOS.debug.dylib.
  • The header change has been in our app (react-native-macos 0.83.0, dynamic frameworks) as a patch-package patch, where it lets react-native-svg 15.16 link.

Not built for iOS or visionOS: both changes are inside TARGET_OS_OSX.

…ation extern "C"

They are defined in RCTUIImage.m, an Objective-C file, so their symbols are C. Declared without extern "C", an Objective-C++ caller looks for C++-mangled names and fails to link on macOS (react-native-svg's RNSVGSvgView.mm, for one). The other two functions in RCTUIImage.h are already declared this way.

RCTImageLoader.mm kept a copy of both functions from when React-RCTImage could not depend on RCTUIKit (microsoft#1611). As C++ its copies had mangled names and never clashed; declared extern "C" they would be duplicate symbols. React-Core depends on React-RCTUIKit now, so the copy goes and the image loader uses RCTUIKit's.
@brondavies
Bron Davies (brondavies) requested a review from a team as a code owner October 23, 2026 15:07
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

This branch has not been deployed

No deployments
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.

macOS: UIImagePNGRepresentation and UIImageJPEGRepresentation fail to link from Objective-C++

1 participant