Skip to content

Add Kotlin/Native Wrapper #719

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 84 commits into from
Feb 19, 2024
Merged

Add Kotlin/Native Wrapper #719

merged 84 commits into from
Feb 19, 2024

Conversation

ISNing
Copy link
Contributor

@ISNing ISNing commented Feb 8, 2024

  • Binding to Kotlin/Native based on C-API
  • Build CI
  • Build CI environment fix
  • Publish CI
  • Documentation
  • Tests
  • Rebase the commits

@axxel
Copy link
Collaborator

axxel commented Feb 9, 2024

First of all: I'm impressed. You had to develop your own gradle plugin to build cross-compiled cmake based native code?!?

I had already a closer look at your code and it looks pretty good. There are a few things I'd like to see changed before merging, though. One is naming (see #705 and #720). I got a little distracted with that summary. I'll start with some detailed feedback tomorrow, hopefully. At the latest early next week.

@ISNing
Copy link
Contributor Author

ISNing commented Feb 9, 2024

First of all: I'm impressed. You had to develop your own gradle plugin to build cross-compiled cmake based native code?!?

I had already a closer look at your code and it looks pretty good. There are a few things I'd like to see changed before merging, though. One is naming (see #705 and #720). I got a little distracted with that summary. I'll start with some detailed feedback tomorrow, hopefully. At the latest early next week.

I develop my own gradle plugin because I hope to integrate the whole building progress into ci, but not to manually build every targets one by one and configure cross compile environment. And the plugin can also be used to binding other c-based library into K/N(Eventually KMP aka. Kotlin Multiplatform)
(PS: To be exact, it's two gradle plugin, the KrossCompile one wrapped another one which directly call cmake)
Thanks for your acknowledgment of my work :)

For the issue of naming, I will correct them today and push them if everything goes well.

What's more, I hope to get some idea about the package name of classes in the wrapper, is simplezxing package appropriate? or io.github.zxing-cpp would be better?

Edit: - is not allowed in package name, so now I choose to align with android wrapper, use zxingcpp package name according to #720

@ISNing ISNing force-pushed the kn-added branch 4 times, most recently from c24acde to d02ad4e Compare February 10, 2024 01:01
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.

There is a lot to cover. I'll just start and see how far I get today...

There are open questions regarding how to most naturally model the ReaderOptions, ImageView and BarcodeReader API.

@ISNing
Copy link
Contributor Author

ISNing commented Feb 11, 2024

Everything seems working well, include ci and tests

@ISNing ISNing marked this pull request as ready for review February 11, 2024 12:13
@ISNing ISNing requested a review from axxel February 11, 2024 14:20
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.

Thanks again for the continued work on this.

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.

We are coming closer to a merge. Thank you.

ISNing added a commit to ISNing/zxing-cpp that referenced this pull request Feb 14, 2024
@axxel
Copy link
Collaborator

axxel commented Feb 14, 2024

Sorry for the inconvenience but my recent commit requires a number of changes before merging.

@axxel axxel merged commit 74319f2 into zxing-cpp:master Feb 19, 2024
@axxel
Copy link
Collaborator

axxel commented Feb 19, 2024

Thanks for your patience and endurance. :) Let's hope people find this useful.

By the way: what is your use case for this?

@ISNing
Copy link
Contributor Author

ISNing commented Feb 19, 2024

I'm currently working on an multiplatform app used for a student organization and it needs a library for scanning qrcodes.
The app has no strict deadline. You know, the kmp community is still in its initial stage and lack of many out of box libraries for easily creating multiplatform apps. If I don't create a library published, then I will still have to bind libraries in my app and when it comes to others need this, they will have to build a wheel again. If I do, others will benefit from this out of box library.
And enjoy their development. ;)

The next I will do is to try to unify this binding with many other non-native platforms such as jvm and js. (I didn't do that here because I think it's wierd to create a binding to java and js version of zxing inside repo of zxing-cpp)

@ISNing ISNing deleted the kn-added branch February 19, 2024 10:39
@Phaestion
Copy link

@ISNing @axxel thank you for the work here, this looks amazing! We are more interested in the generation side of barcodes but it seems that this is not currently covered here. We'd be happy to contribute in this regard based on the excellent work done by @ISNing.

Also just a quick question, you mention that this is available in Maven Central, but it seems it's not listed there yet. Does it need time to propagate? Or am I missing something?

@oehhar
Copy link

oehhar commented Feb 27, 2024

Steyn,
great to read your name here. xzing-cpp is a great extension, but the generation part is quite unmaintained and outdated. Please check out the zint project, or bwipp, if your target is postscript.
Both are well maintained and use zxing-cpp for autoated testing.

Awesome work,
Harald

@axxel
Copy link
Collaborator

axxel commented Feb 27, 2024

it seems that this is not currently covered here.

That is correct.

We'd be happy to contribute in this regard based on the excellent work done by @ISNing.

Very good to know. Also nice to hear that someone (except for @ISNing) is actually interested in this new code :)

The main reason the writing part is not present a.t.m. is basically because of this very dated initiative: #332. The current MultiFormatWriter API must not be allowed to spread further ;). I am indeed in the middle of finally addressing this, see, e.g. #724. Feel free to comment on the matter and express your requirements. In terms of coding, there is nothing yet to do until the API is finalized.

Also just a quick question, you mention that this is available in Maven Central, but it seems it's not listed there yet. Does it need time to propagate? Or am I missing something?

That is correct. I have not done a release, yet. That is also tight to the #724 discussion, which I'd like to settle before the new Rust, .NET, K/N wrappers are properly released.

@axxel
Copy link
Collaborator

axxel commented Feb 27, 2024

xzing-cpp is a great extension, but the generation part is quite unmaintained and outdated. Please check out the zint project.

I fully agree with @oehhar. That is exactly why I'll be using zint as a backend for the writer. The upshot from a user perspective is going to be the ease of use, e.g. via the list of existing and upcoming wrappers. The benefit for the zint project would be the extended reach via those same wrappers (including c++ in this case).

@Phaestion
Copy link

Hi Harald @oehhar ! Great seeing you here too. :) Thank you for pointing zint out, I believe I have looked at this in the past. For this to work for us we would need wrappers in Java (pretty simple), Kotlin/Native (should be simple if we could build on the work and plugins developed above - or at least use them for guidance), WASM (I believe this can be done via emscripten).

@axxel thanks for the links and info regarding the discussions.

I fully agree with @oehhar. That is exactly why I'll be using zint as a backend for the writer. The upshot from a user perspective is going to be the ease of use, e.g. via the list of existing and upcoming wrappers. The benefit for the zint project would be the extended reach via those same wrappers (including c++ in this case).

This sounds good to me! From our perspective we would mostly be interested in the generation side, so this leads to the question, where would our efforts best be spent? From the wrapping perspective in Java, Kotlin/Native, WASM building on the zint base would probably make more sense, seeing as the common denominator for the platforms we're interested in is mostly C and not C++. (Of course I'm saying this without having spent any meaningful time in exploring the zint code base.)
If that would then be useful in this repo I guess it can be pulled in as well.

@oehhar
Copy link

oehhar commented Feb 27, 2024

The original zint web-site cites ports to Java and .Net.

@axxel
Copy link
Collaborator

axxel commented Feb 27, 2024

This sounds good to me! From our perspective we would mostly be interested in the generation side, so this leads to the question, where would our efforts best be spent?

At first, participating in the discussion about requirements would help the most. I summed up the current situation in a new discussion: #739. Let's please move any further conversation regarding this topic over there. If the API and feature-set discussion has concluded, there is a need to 'type that out' in the different wrappers but that should actually not be too much work, once the foundation in the c++-backend is set.

From the wrapping perspective in Java, Kotlin/Native, WASM building on the zint base would probably make more sense, seeing as the common denominator for the platforms we're interested in is mostly C and not C++. (Of course I'm saying this without having spent any meaningful time in exploring the zint code base.) If that would then be useful in this repo I guess it can be pulled in as well.

I already have a relatively clear path forward in my mind (see #739). I would hope that your priorities either already align with those stated there and if not, that we can all agree on a suitable way forward. But I will not be interested in merging something like a 'plain wrapper` around the libzint API. I care about consistency and ease of use - and performance, but that is mostly an issue on the reader part of the problem domain.

@ISNing
Copy link
Contributor Author

ISNing commented Mar 6, 2024

I'm currently working on an multiplatform app used for a student organization and it needs a library for scanning qrcodes. The app has no strict deadline. You know, the kmp community is still in its initial stage and lack of many out of box libraries for easily creating multiplatform apps. If I don't create a library published, then I will still have to bind libraries in my app and when it comes to others need this, they will have to build a wheel again. If I do, others will benefit from this out of box library. And enjoy their development. ;)

The next I will do is to try to unify this binding with many other non-native platforms such as jvm and js. (I didn't do that here because I think it's wierd to create a binding to java and js version of zxing inside repo of zxing-cpp)

And here is finally it is: https://github.com/ISNing/ZXingKMP
It's still in a very initial stage and need to add more tests to ensure it's function
And there are also many helper functions should be added for compose for easier using the scanner.

And I finally find zxing-cpp is already far from the original ZXing java implementation, and has added many features (Sorry for didn't realize this before)

(These differences indeed makes a big trouble binding them to a unified interface, If possible in the future, I hope to switch them all to use jni or sth to call zxing-cpp)

P.S. For me lacking knowledge in this area There are many behavior not aligned between java target and native target
If anyone can give some tips in your free time I would be grateful. You can find them here ISNing/ZXingKMP#13

P.S.2 Also looking forward to the kn wrapper's publishing

@axxel
Copy link
Collaborator

axxel commented Mar 6, 2024

@ISNing Thanks for sharing this information. I have not looked much into it yet. But I have an issue with the kn build after some cmake changes. Can you make sens of that error message: https://github.com/axxel/zxing-cpp/actions/runs/8180140576/job/22367578496 ?

@axxel
Copy link
Collaborator

axxel commented Mar 9, 2024

@ISNing I'm sorry to inform you that I'm about to make yet another change (that would actually kind of obsolete your most recent fix :-/). My new idea is to add a conditional #define ZXING_HAS_READERS in an auto generated Version.h. This basically solves the same problem but has the advantage that any client-code built completely independent of the cmake build system can pick up that configuration option. The downside is that it complicates the build of the library when non-cmake tools (like bindgen from rust or the swift package manager) are involved. Your own cmake plugin currently also does not support autogenerated files, that end up in the build-dir, see this error.

I don't even know whether that approach is going to end up in zxing-cpp but maybe you'd like to fix your plugin anyway to be able to work with any cmake library using configure_file?

@ISNing
Copy link
Contributor Author

ISNing commented Mar 10, 2024

I don't even know whether that approach is going to end up in zxing-cpp but maybe you'd like to fix your plugin anyway to be able to work with any cmake library using configure_file?

Yes, absolutely I'll fix that.
And now I've done fix here: axxel#3

@axxel
Copy link
Collaborator

axxel commented Mar 16, 2024

@Phaestion @ISNing After there has been zero discussion/feedback about the writer API strategy, I went ahead with what I outlined. This is still not final in terms of which properties are exposed but if you are interested in working on the Kotlin/Native part of the creator/writer API, now would indeed be a good time to look into this. I already added the Python and Rust API and would likely look into .NET next.

@ISNing
Copy link
Contributor Author

ISNing commented Mar 18, 2024

@Phaestion @ISNing After there has been zero discussion/feedback about the writer API strategy, I went ahead with what I outlined. This is still not final in terms of which properties are exposed but if you are interested in working on the Kotlin/Native part of the creator/writer API, now would indeed be a good time to look into this. I already added the Python and Rust API and would likely look into .NET next.

Good to hear that! I will look into that and implement the writer api as soon as I have enough free time!

@axxel
Copy link
Collaborator

axxel commented Dec 28, 2024

@ISNing I'm finally about to make the next release, which would be the first that "includes" your wrapper. I took this as a nudge to look into the naming of the API again. The motivation being to keep at least the 3 new wrappers as consistent as the different technologies allow. Since the writer API is still considered experimental, I don't worry too much about that but there is one function (BarcodeReader::read) in your wrapper that currently is not in line with the .NET and the rust wrapper.

Would you mind if I renamed this function to from. Note that I would not change the 'static' function of the companion obect.

See also e.g. the .NET wrapper and the discussion in #724 and especially this comment

@ISNing
Copy link
Contributor Author

ISNing commented Jan 1, 2025

I don't have any research on C#, but I think it's obvious that BarcodeReader::from is not very semantic, a BarcodeReader can do read, but a BarcodeReader does from but gives out Barcodes doesn't make sense, a more appropriate and convenient one might be Barcode::from(ImageView, ReaderOptions), This can be interpreted as instantiating a Barcode from arguments.

For ease of use, we can even expand ReaderOptions to the function and make it Barcode::from(ImageView, *ReaderOptions), since in most cases we only need to set a few parameters, which reduces the construction of a ReaderOptions instance. Considering that cinterop calls passing values as arguments can have a lot of overhead (I mean memory copying, not sure if there really is), and it may not be very cost-effective during continuous scans, we can also choose to keep two designs, one for a single scan and one for multiple scans in a row, to avoid overhead.

This is only considered from the semantics of the function, and does not consider the difficulty and consistency of the actual implementation, and just a liittle advice

axxel added a commit to axxel/zxing-cpp that referenced this pull request Apr 8, 2025
This adds an `append(BytesArray&&)` overwrite to support the `{data, size}`
based call from within `CreateBarcode` function.

See also
zxing-cpp#719 (comment)
axxel added a commit to axxel/zxing-cpp that referenced this pull request Apr 8, 2025
This adds an `append(string_view<uint8>)` overwrite to support the
`{data, size}` based call from within `CreateBarcode` function.

And removes the use of `using enum`, sigh...

See also
zxing-cpp#719 (comment)
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.

5 participants