-
Notifications
You must be signed in to change notification settings - Fork 139
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
C# Bindings/API #67
Comments
Hi! Two things:
Here's the subset of the API that would be used by the C# bindings. (in ruby FFI syntax). Check imageflow.h for param names.
Note that that the last two API functions will be refactored to use JSON instead of structures. This refactoring hasn't taken place yet. Hopefully this helps provide a sense of the (limited) scope of work required. We have no documentation right now about the JSON schema that will be used, but hope to publish that soon. |
FFI API docs are now online. The interface should be pretty stable, but there is a slight chance that memory ownership semantics will be forced to change as more of the core is ported to rust. These are uploaded as part of CI, and should be updated daily. https://s3-us-west-1.amazonaws.com/imageflow-nightlies/master/doc/imageflow_core/abi/index.html |
Ideally we won't see FFI breakage, but rather spend more time refining the JSON message API, which should be much easier to debug. |
@nathanaeljones trying to view the index gives me a 403 |
I fixed the link, sorry! Did some reorganization. There are also windows binaries of libimageflowrs.dll available, although the JSON message API only responds to "teapot" at the moment. https://ci.appveyor.com/project/imazen/imageflow/build/1.0.307/job/6edn741gtjnouyk9/artifacts |
Let me know if I can improve the clarity of the API docs. There's not much to document on imageflow_send_json yet, but those schemas should be coming this week. |
@SamuelEnglard, will #81 be problematic for the C# API? I don't know that you'll need to use the error reporting API until we get to implementing custom I/O wrappers in C# for, say, Stream classes, at which point |
#81 will be an issue in that there's just no way to not transfer the C string memory to the GC's control. The best we could do would be to have C# allocate the error message memory and we fill it. |
New docs, small API changes, but much higher confidence level: https://s3-us-west-1.amazonaws.com/imageflow-nightlies/master/doc/imageflowrs/index.html |
Ruby bindings have been updated and are passing all tests again. Over 60% of bugs were discrepancies between camelCasing and snake_casing. |
The JSON API docs now live here: https://s3-us-west-1.amazonaws.com/imageflow-nightlies/master/doc/context_json_api.txt There is finally some documentation on packaging native binaries in .NET: https://github.com/dotnet/docs/blob/master/docs/core/tutorials/libraries.md#how-to-use-native-dependencies Would you plan to target .NET Standard 1.5? |
I'd try to target as low as I can, so hopefully 1.3. |
If you can use help testing the c# wrapper let me know! |
BTW, I'm happy to write the P/Invokes if that would help. It's reasonably trivial for me - the non-trivial bits are tooling/packaging/CI/release/scripts due to the cognitive space and context switching required. If you want, the low-level bindings (and perhaps JSON (de)serialization schema/classes) could even go in this repo, under bindings/dotnet, so that they can be tested against each release. (Can the .NET Core tooling fit in 100MB? I could install it on the docker containers.) |
My thinking/hoping is to have the P/Invoke and JSON (de)serialization code generated by T4 or Scripty. That way as you make changes they are updated with no issue. The Core tooling should, really depends on the size of our dependancies |
P/Invoke is easier by hand. I've invested incredible amounts of time into trying to automate that stuff - CppSharp, SWIG, and at least six others. There's just too much loss of information to make it work. As far as JSON serialization, the easiest path would probably be to find something that works similar to Serde.rs and duplicate the types. Serde can't generate schemas or Swagger or anything yet, so my instinct would be to set up roundtrip tests between C# and Rust to ensure nothing is lost. |
I only plan to automate the functions themselves. The structs and such I'd write by hand. I plan to use JSON.NET under the hood, but for the best performance I don't want to use the reflection API. |
Do you need me to make a C header file? What's the expected input and tool?
Fair enough. I don't think reflection can handle discriminated unions in C# anyway (just F#) - so code generation might come in handy there. |
I was overthinking this. C# needs to do very little parsing. Primarily, it needs to serialize - which is easier. I could expose a 'mirror' API in libimageflow that just parses and re-serializes. If we disable whitespace and have the same rules for empty field omission, then it should be easy to compare the strings and verify that Rust is actually seeing everything that C# is sending. Thoughts? |
A C or even C++ header would be easiest to work with. The easiest tool to work with would be the P/Onvoke Interop Assistant. It's not perfect in its generation but put its output is a good starting point.
Not sure myself so a good point. |
Here's a C header: https://gist.github.com/nathanaeljones/74f58b2d3aee3831eb3efdd316db77e0 All 4 structs are opaque. Keeping track of 4 kinds of pointers isn't hard, but I discovered today that P/Invoke supports typed pointers via Also, good reference on GC/Pinvoke race conditions: https://blogs.msdn.microsoft.com/bclteam/2005/03/15/safehandle-a-reliability-case-study-brian-grunkemeyer/ I like GC.KeepAlive() for it's explicit handling of the issue. I don't have the interop assistant handy - can you let me know what that header file produces? |
I personally create structs that wrap the pointers usually, since it removes the need for unsafe and can have helper code. I had to modify the header file slightly for the tool to be happy. Two issues where that I didn't have the imports for the int types (so I just stubbed them) and that just doing empty struct declarations is not enough for it (so I just typedef-ed them as |
It looks like we're getting "ref IntPtr". Any idea why? Typedef? I can fully erase the types if you want. |
I made the structs |
I've added automatic header generation as part of the build process. Here's one with types erased: https://gist.github.com/nathanaeljones/023fe6f3e271d6e72cf0b8c3de5013b2 |
As I'm going through the C header I have some questions. Why do you use |
Woot! This is still under development: https://github.com/jaredpar/pinvoke Also, the integration server is now running RTM 1.0. |
@nathanaeljones That's awesome! |
I'd like to spike a partial wrapper for Imageflow that doesn't do any abstractions at the P/Invoke layer, but just uses IntPtr. Do you have the raw output from a P/Invoke generation tool handy? |
Not home tonight but tomorrow night I should be able to get that to you 👍 |
About two months late but... https://gist.github.com/SamuelEnglard/557c7b549a2a30a245a1b8a21fd9d2a7 |
Thanks @SamuelEnglard . I was curious on the project and checked in yesterday and saw there wasn't much movement lately. I'm interested in these C# bindings you've been working on. I wish I had time to test or help out. But I'm happy to see your commit. |
@RossLieberman Yeah... Massive shake ups at work have me falling behind on lots of stuff. Finally trying to get back into it |
Thanks for work on .Net bind @SamuelEnglard |
@CShepartd planning on publishing to NuGet once their is a public API. The current code is all internal. Can't really give a time line on that. |
@SamuelEnglard Thank you, but that's not the right header; you should be using https://github.com/imazen/imageflow/blob/master/bindings/headers/imageflow_pinvoke.h |
@nathanaeljones I had feeling it wasn't but figured better try and redo. Leaving work now, when I get home I'll regenerate (and check the primary libraries signatures) |
@nathanaeljones Updated the gist |
@SamuelEnglard What's the best path for using this in a .Net Core app in the meantime? I expect until this becomes more official I'll at least need to create some kind of routing rules/middleware on my own - no worries there. I was able to take the binding work here, target .Net 2.0 Core Preview 2 - and then create my own local nuget package for import. That all worked fine: As you've already mentioned, and I've seen in the source - the C# bindings don't seem to have any publicly exposed methods. In destination project I'm not able to-do anything besides see the namespaces exist effectively. I don't have an issue with having to-do build out to make this work, but I'm trying to avoid unnecessary work and/or false starts. Thanks in advance for the help! |
@OpenSpacesAndPlaces your best bet at this time is to use the HTTP server (imageflow_server) for now. It's not the best solution but for a CMS that should work. |
As a general update: Current issue I'm dealing with is how to work with images embedded in the JSON stream. Since one of the big goals of imageflow is performance I do not want to do it the quick and easy way. Right now that means I may have to write my own JSON parsing system. Obviously don't want to do that so been playing around trying to see what options I have. My goal for the C#/.NET bindings is that .NET users can use this with no understanding of native code ideas. That means lots of wrapping logic. As noted, the current code is all the raw wrappings, P/Invoke code that I do not want end users to deal with. I am going to abstract that away with more .NET styled APIs. |
Maybe we should table implementing embedded images, and assume that we'll use the job api instead of the build api (the job api takes pointers to buffers). |
That's been one thought I had as well. I may just do that |
I think it's very acceptable for 1.0 to only support byte arrays for input and output. |
I had the same problem like @OpenSpacesAndPlaces and give up with ImageFlow and created own multiplatform P/Invoke wrapper of FreeImage (based on https://github.com/matgr1/FreeImage-dotnet-core). I needed only resize images and working well ImageFlow is one of the biggest disappointment on my list (slow development, bugs, no goals/milestones etc.). Just sad |
Today I wrote a minimal C# wrapper for Imageflow: https://github.com/imazen/imageflow/tree/master/bindings/dn This exposes both the JSON graph API and the ImageResizer4 quersytring API. @CShepartd I'm sorry that imageflow has been disappointing for you. Is this primarily about the C# wrapper, or do you have concerns about the project itself? We do have a roadmap, and bugs are to be expected. We anticipated that more people would give imageflow a try and provide feedback, but that volume has been extremely low. |
Note: 9700421
Improvements to ABI
|
Quick, any reason not to merge context and job? Contexts are smaller/quicker now. JobContext would be simpler. Io objects would get an io_id upon creation. Can you think of any use case that would suffer from this change? /cc: @SamuelEnglard |
Nothing off the top my head |
Thoughts on this API? bool imageflow_abi_compatible(uint32_t imageflow_abi_ver_major, uint32_t imageflow_abi_ver_minor);
uint32_t imageflow_abi_version_major(void);
uint32_t imageflow_abi_version_minor(void);
void* imageflow_context_create(uint32_t imageflow_abi_ver_major, uint32_t imageflow_abi_ver_minor);
bool imageflow_context_begin_terminate(void* context);
void imageflow_context_destroy(void* context);
bool imageflow_context_has_error(void* context);
bool imageflow_context_error_recoverable(void* context);
bool imageflow_context_error_try_clear(void* context);
int32_t imageflow_context_error_code(void* context);
int32_t imageflow_context_error_as_exit_code(void* context);
int32_t imageflow_context_error_as_http_code(void* context);
bool imageflow_context_error_write_to_buffer(void* context, char* buffer, size_t buffer_length, size_t* bytes_written);
bool imageflow_context_print_and_exit_if_error(void* context);
bool imageflow_json_response_read(void* context, void const* response_in, int64_t* status_as_http_code_out, uint8_t const** buffer_utf8_no_nulls_out, size_t* buffer_size_out);
bool imageflow_json_response_destroy(void* context, void* response);
void const* imageflow_context_send_json(void* context, char const* method, uint8_t const* json_buffer, size_t json_buffer_size);
bool imageflow_context_add_file(void* context, int32_t io_id, imageflow_direction direction, imageflow_io_mode mode, char const* filename);
bool imageflow_context_add_input_buffer(void* context, int32_t io_id, uint8_t const* buffer, size_t buffer_byte_count, imageflow_lifetime lifetime);
bool imageflow_context_add_output_buffer(void* context, int32_t io_id);
bool imageflow_context_get_output_buffer_by_id(void* context, int32_t io_id, uint8_t const** result_buffer, size_t* result_buffer_length);
void* imageflow_context_memory_allocate(void* context, size_t bytes, char const* filename, int32_t line);
bool imageflow_context_memory_free(void* context, void* pointer, char const* filename, int32_t line); |
Implemented. |
Looks good to me |
@SamuelEnglard I'm planning to move the new .NET bindings to their own repository (We now have a versioned ABI, and a separate repo allows for a much quicker release cycle for the bindings). To reduce confusion I'd like to move your bindings elsewhere as well. |
The bindings are now on NuGet https://www.nuget.org/packages/Imageflow.Net/ The project has been moved to https://github.com/imazen/imageflow-dotnet |
Please test out Imageflow.Net and provide feedback at https://github.com/imazen/imageflow-dotnet/issues |
I wanted to start the conversation on the C# Bindings/API
Primarily at this point that means designing the API surface.
The text was updated successfully, but these errors were encountered: