Skip to content

Adding a wrapper for iOS #337

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

Merged
merged 92 commits into from
Jul 13, 2022
Merged

Adding a wrapper for iOS #337

merged 92 commits into from
Jul 13, 2022

Conversation

parallaxe
Copy link
Contributor

Co-authored-by: Christian Braun braun.christian.bamberg@gmail.com

This pull request adds a wrapper of ZXing for iOS. It offers one class for reading and one for writing.
ZXing itself will be compiled to an universal framework, xcframework, that contains the binaries and
headers for the iOS-simulator and for iOS-devices. The wrapper-code is written in Objective-C++, whereas
the public part of the wrapper is Objective-C only. By this, it can also be used in Swift.

To build the xcframework, I had to add a section to the CMakeLists.txt. This enables building frameworks
for Apple platforms. Those frameworks are only either for the simulator, or for real devices. But they can be
combined to a single xcframework. This process is automated by the build-release.sh-script.
The section in the CMakeLists.txt should not change the behaviour on other platforms (tested on Linux so
far).

To use the wrapper, you first have to build the xcframework by calling the build-script and then adding
the Package.swift-file to your project. A demoproject is included, where also the usage is demonstrated.

@axxel
Copy link
Collaborator

axxel commented May 24, 2022

Hallo Hendrik und Christian, thanks for your offer to contribute, much appreciated. I skimmed through your PR and have a few comments and suggestions for improvement. First, a few general things:

  1. Are you willing and in the position to 'take care' of this code in the longer term? I'm asking this because I have no experience with ios/ObjectiveC and I can't even compile the code myself. The public facing API is going to change in the future (see e.g. How to improve binary data support? (Community feedback requested) #334, Discussion about the future of the barcode generation / writer part of this project #332 and Please bump SONAME following API breakage #333 for a few current discussions), so the wrapper will need to be kept up-to-date and if the code does not even build anymore in 6 months from now, then there is not much point in adding it.
  2. You have no license attribution attached to your source files. Please follow the recent addition of // SPDX-License-Identifier: Apache-2.0 comments. Also, please consider removing the comments that state the file-name and change the Created by ... lines to Copyright 2020 <name of entity>.
  3. Is the ObjectiveC/C++ part minimal? Or would there be room to convert more of that code to Swift? (On the android side there is everything in Kotlin and nothing in Java).
  4. Have you looked into the possibility to replace the build-release.sh with standard cmake code?
  5. We definitively need to hook that wrapper into the CI system before merging (see also point 4.)
  6. Do you care about the writing part yourself (right now) or did you add this more for sake of completeness?
  7. I see 2 names related to the packge/lib as a whole: ZXing and ZXingWrapper. I'd like to stay as consistent with the rest of the project as possible. The python and the android wrappers use the name zxing-cpp / zxingcpp (e.g. the python package is called zxing-cpp but the module is called zxingcpp because modules can not have '-' in their names). The names were chosen primarily to prevent a naming clash with "upstream" wrappers. The project keeps moving away from Java ZXing (in terms of API, capabilities and performance) and therefore I became more and more fond of actually having that different name. The c++ library itself is called ZXing but from today's perspective, I'd rather have that be zxing-cpp as well. How that would map best to the two names and how much best practice from the ios world went into your choice, I can't say. Please explain.

@axxel
Copy link
Collaborator

axxel commented Jun 2, 2022

Since you did not react to my comments, yet, I'm wondering if I completely put you off with that feedback. If so, I'd like to invite you shortly describe what part of it was too much, so I may learn from my mistakes :).

@parallaxe
Copy link
Contributor Author

Hi Axxel, thanks for your thoughtful analysis.

Regarding your questions:

  1. We (and with 'we' I mean the company KURZ Digital Solutions) will maintain the wrapper over long term, yes. We already use the 'old' zxing in multiple apps and will migrate to this fork over time and also use it for new apps. If there as a need to update the iOS wrapper, we will do so.
  2. Updated and pushed 👍 .
  3. Yes, I consider this as minimal. As there is no interoperability between C++ and Swift, we need ObjC++ as glue-code. But as the included demo-project shows, the API is also nicely usable with Swift out of the box.
  4. To be honest, no. I circle around cmake and its obscure syntax whenever possible. If it is a hard requirement, I will migrate it. But from our experience and other build-scripts we are using, the xcodebuild-commands are stable over the years and we expect no real effort in maintaining the build-script.
  5. Yes, I agree. It seems like that the CI is based on github workflows. I haven't worked with them yet, but it looks like that there are also free macos-runner that we could use to build the xcframework and the demo-project. I will try to configure a workflow for it. Or can we modify the existing macos-configuration? Does this sound feasible to you?
  6. We have an app in the Apple AppStore ("Code Scan") that allows the user to create barcodes. This is currently done by the 'old' zxing, but we will migrate it to this fork. This is currently the main source of the requirement for the writer and the reason why it is included. There are currently no plans of integrating the writer-part in other apps, but you never know. 😬
  7. The naming-scheme of the ZXing.xcframework is quite common (starting with uppercase-letters), so I would leave it as it is. I agree that the name of ZXingWrapper is a bit off and we should change it. But I have to look up the conventions of SPM-package-names (Swift Package Manager) and if there even is a conclusion yet by myself first.

Copy link
Collaborator

@axxel axxel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went over the code again and started with a bunch of individual comments.

@ryantrem
Copy link

ryantrem commented Jun 6, 2022

I'm looking at possibly using zxing-cpp for cross platform barcode scanning, so I was happy to see this PR 🎉. I just checked out this branch and tried to follow the steps and ran into a few issues though:

  1. There were somewhere around 550 generated build files that were being tracked by git. I added a .gitignore file to the wrappers/ios directory (similar to the other wrapper directories) with the following:
.swiftpm
_builds
ZXing.xcframework
xcuserdata
  1. The pbxproj has your DEVELOPMENT_TEAM hard coded in it (the "Team" under "Signing & Capabilities" in Xcode). I think it would be a little better to set the Team to "None" and save the file that way, which makes it more clear that a Team needs to be specified.
  2. The BitArray.h file is missing from the ZXing.xcframework/ios-*/ZXing.framework/Headers directories and so the build fails for the sample app. If I manually copy that file over, then it compiles successfully. I'm guessing something is supposed to be copying this file but is not for some reason.
  3. The sample app crashes on launch for me with Library not loaded: <repo root>/zxing-cpp/wrappers/ios/_builds/core/Release-iphoneos/ZXing.framework/ZXing. It seems like the lib is either not loading or not present. This is where I got stuck, so not sure if there are any other issues beyond this!

@axxel
Copy link
Collaborator

axxel commented Jun 7, 2022

@ryantrem Thanks for joining the discussion and sharing your experience. Since I can't test the code myself, it is highly appreciated to have some 'external' feedback. I'd like to say something about 2 of your points:

  • ad 1. sounds good, should be included one way or the other (cmake generally prefers out-of-source builds but on the android side we have a similar issue, so if this is how the iOS projects are to be setup...)
  • ad 3. That is a compile regression that I accidentally introduced with my merge commit. I believe the right way forward is to remove the dependency on this header inside the writer implementation by not using the BitMatrix::getRow() function and access the bits directly via BitMatrix::get(x, y).

I'll let the authors comment on the other two.

@ChristianNorbertBraun
Copy link

@ryantrem Thank you for checking out this PR!
I tried to reproduce the error you mentioned in point 4, unfortunately without success.
Could you check if the framework is listed within the Frameworks, Libraries, and Embedded Content under the General tab of the demo application?

@axxel
Copy link
Collaborator

axxel commented Jun 21, 2022

@ChristianNorbertBraun thanks for picking this up again. Sorry for being so blunt but we seem to move 2 steps forward and then 1 step back:

  • You partly reverted changes I made recently (completely unrelated to your wrapper, see Content and Result).
  • The core/CMakeLists.txt now seems to contain your additions 3 times.
  • Your new Point related files have the wrong license/copyright comments again.

@ChristianNorbertBraun
Copy link

ChristianNorbertBraun commented Jun 21, 2022

@axxel All good, thank you for your feedback. I'm sorry for the inconvenience. I will try to clean up this mess tomorrow.

axxel and others added 13 commits June 22, 2022 10:30
disable blackbox tests by default and tune ZXingReaderTest to not fail
when samples folder is missing.

This fixes zxing-cpp#312.
Deprecate the namespace `CharacterSetECI` and header and use name
consistent with `BarcodeFormatFromString()`.
Fixes zxing-cpp#168. This has been tested to work with the example applications.
This is a pretty sharp "deprecation" of a whole lot of internal API and
reduces the published interface to merely `ReadBarcode` and
`MultiFormatWriter`. It is obviously somewhat risky but I see no other
practical way of moving forward with limiting the API.
@ChristianNorbertBraun
Copy link

We've added a build-ios job within the ci.yml. Is this sufficient for ci integration?

@parallaxe parallaxe requested a review from axxel July 1, 2022 12:37
Copy link
Collaborator

@axxel axxel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fmtlib-src git submodule that you accidentally added needs to be removed again.

I was looking for the developer team name (or whatever it was called) to see if it was cleared but could not find it anymore.

width:(int)width
height:(int)height
format:(ZXIFormat)format
charset:(ZXICharset)charset
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is still an open question.

@ChristianNorbertBraun
Copy link

The team was set to none here: 7f6256f


NSMutableArray* zxiResults = [NSMutableArray array];
for (auto result: results) {
if(result.error() == Error::None) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not compile. The way to go here is using result.isValid(). But if you don't pass DecodeHints::returnErrors(true) and the default is not to, then all returned results are valid, so this check can completely be removed.

Also, the next line uses .c_str() which will fail if the text() property contains a \0 byte, which may be the case.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out.

Regarding the c_str(). I'm afraid I don't quite understand. The function call actually expects a null terminated string. And doesn't a cstring contain a \0byte per definition?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a cstring ends with a \0 but the point is that the utf8 encoded content here may contain a \0 byte somewhere in the middle of the string. That is uncommon but possible and might lead to weird/silent bugs down the line. Better to fix it right here. Please use initWithBytes with NSUTF8StringEncoding. That should do the trick.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0

#define ZX_USE_UTF8
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the back and forth but since this PR was too late for 1.4.0 and will now be part of 2.0 (I hope) this define is not necessary anymore and would merely be noise.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good, I removed the define

@axxel axxel merged commit 7ebada5 into zxing-cpp:master Jul 13, 2022
@axxel
Copy link
Collaborator

axxel commented Jul 13, 2022

Thanks a lot for your continued and cooperative work on this. Let's hope it further broadens the reach of the project.

@axxel
Copy link
Collaborator

axxel commented Jul 13, 2022

Something I only noticed now: the build time of the ios CI block is longer than any other. The demo-app alone takes 5 minutes to build, which seems excessive also compared to the faster build of the framework which has way more files to process (and is c++ instead of swift/objective-c). Is that also the case on your development machine? Any idea why that is and if something could be done about that? maybe a missing parallel build flag?

@ChristianNorbertBraun
Copy link

We will take a look into it! Thank you for the collaboration.

@ChristianNorbertBraun
Copy link

Building the demo app on my machine takes about 1 minute.
Looking into some of the more recent builds this is also what the ci runner needs:

So maybe the 5 minute build was some problem with a single runner. As I can not reproduce these long build times I consider this problem as solved.

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.

4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy