-
Notifications
You must be signed in to change notification settings - Fork 231
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
callback with user data #345
Conversation
Hi @Joylei, thanks for this contribution. This is pretty much how I would have done it. I want to hold on to this for a bit while I find out what is possible and what is not within Java and specifically JNA and find out from @jkoplo and @timyhac what works for C#. API changes are set in stone once they happen so I want to make absolutely sure this is the right way to do it before I add this function. I can always add API functions, but not change or remove them without breaking old code. I wonder if rather than void* as the type for the data, we'll need to use intptr_t or uintptr_t which should be the same size. Java, for instance, stores pointers as the long data type. But most wrappers can handle void* because it is such a common C idiom. The key thing I am trying to determine is what happens on GCed systems. For instance in the JVM world, the garbage collector can move objects. So if there is no way to somehow track the changing pointer, then the C code will call the callback with an invalid pointer and possibly crash the VM. While, to some extent, this is the responsibility of the application/wrapper, I want to make sure that there is a very clear explanation of how to do it right or have code that does it right. Again, thanks for this contribution! |
Also, probably the name should be plc_tag_set_callback_ex() to make it clear that this is an extended version of the callback system. I would also want to add @timyhac's request of having a PLCTAG_EVENT_CREATE_COMPLETE event too and that will require more tweaking. That said, we can just add the event type but not generate it yet. |
I raised issue #235 with the .Net team. |
* VS 2022 does not define WIN32 and only defines _WIN32. This commit fixes shared examples. (libplctag#339) * Fix 341 - fix segfault, use-after-free issue with requests (libplctag#342) * Don't call the tag's abort function if it doesn't have one. * In process. Fix up handling of requests when checking request status. Requests could be deleted out from underneath us. * Refactor request status checking into common code. * Remove refactored common request status checking code. * Add common request status checking code. * Removed commented out old code. * Added missing request reference release. Cleaned up duplicate code from bad merge. * Fix duplicate slash in path. * Fix 341 - bump version (libplctag#343) * Don't call the tag's abort function if it doesn't have one. * In process. Fix up handling of requests when checking request status. Requests could be deleted out from underneath us. * Refactor request status checking into common code. * Remove refactored common request status checking code. * Add common request status checking code. * Removed commented out old code. * Added missing request reference release. Cleaned up duplicate code from bad merge. * Fix duplicate slash in path. * Bump version for request use-after-free fix.
I'm good at .Net. It's not a problem for GCed systems.
I believe there must be a similar mechanism for Java. |
Thanks for the response @Joylei. I got the same response about C#/.Net from that wrapper team. Java is going to be more of a challenge, however we can just include a reference to the original Tag object within the Callback instance so we do not need the passed reference. What data type is preferable to .Net? |
It's common to use |
3ab4986
to
d64ec19
Compare
Thanks, @Joylei! I have moved this to the prerelease branch. I do all PRs (mostly, in emergencies I'll commit to release) to that branch. That is where testing is done. It gives me a chance to catch other merge problems and test result problems. I am going to try to get this merged this weekend. I will do some testing and wiki additions first. |
This is going to end up as version 2.5.0 because it is an API change (SemVer). |
@Joylei I have merged this into the prerelease branch. I fixed up how callbacks are called to conform to the C standard. You cannot "legally" cast a function pointer from a void pointer. There are platforms where that won't work. C, however, does let you cast a function pointer to another function pointer. And due to the way that C marshals arguments, a caller can pass more arguments than a callee will use without danger. I added a few tests and fixed up a couple other things along the way (unrelated). Please test and make sure it passes your internal tests! If it looks good I will push this out as version 2.5.0. The new minor version is due to the fact that this has an API change. I still need to update the API wiki. |
* Don't call the tag's abort function if it doesn't have one. * Remove refactored common request status checking code. * Add common request status checking code. * Fix duplicate slash in path. * Bump version for request use-after-free fix. * callback with user data (#345) * add callback with user data * add test_callback2 * rename plc_tag_register_callback2 to plc_tag_register_callback_ex * rename test_callback2 to test_callback_ex * refer to each other * start fix ups of version. Co-authored-by: Kyle Hayes <[email protected]> * Break apart the ifdef checks as something in Intellisense is breaking and setting _WIN32 even on Linux. * Add test_callback_ex to POSIX build. * Rename string.c to string_standard.c to support better string documentation. * Fix string docs and examples (#347) * Rename string.c to string_standard.c to support better string documentation. * Split string examples into standard and non-standard. * Update example docs to describe new string examples. * Add string tests for standard and UDT strings. * Fix up extended callback code. Type of function pointer is not castable to/from a void pointer. Formatting. (#348) * Synthesize create events. (#349) * Fix version comment, version 2.5 now. * Synthesize create events. Needs to be reworked when event queuing is done. * Fix event status (#350) * Add better (?) status handling for tag events. * Raise and fire events with new functions. * Add status output. Fix required version on test_callback_ex.c. * More event fixes. Don't synthesize created event on started events. Missed special tag created event raise code. * Add @Joylei's windows event test. * Change code to use extended callback and only wake one thread instead of all threads. * Add create callback and fix missing events and duplicate events. (#351) * Make mutex locking recursive. * Raise a read started event when the initial read is triggered. * Add callback to creation args so that early events can work. * Fix event handle to avoid duplication, drops and handle early events. * Clean up example of simple callback. * Add create callback (#353) * Make mutex locking recursive. * Raise a read started event when the initial read is triggered. * Add callback to creation args so that early events can work. * Fix event handle to avoid duplication, drops and handle early events. * Clean up example of simple callback. * Add new ignorable directory to .gitignore. * Remove direct calls to callback function and use raise and dispatch functions. * DS_Store again. Where is this coming from? * Add debugging output of status when raising an event. * Add casts to force status to correct size. * Yikes, caught typo of plc_tag_destroy() called instead of plc_tag_decode_error()! * Wasn't checking for test_callback_ex to exist before running tests. * Backout change to aid merge. * Add missing check for test_callback_ex. * Output status when DELETE event is raised. * Handle tag deletion events. Co-authored-by: joylei <[email protected]>
This PR makes it possible to pass user data to the callback function, as #212 requested.
A new api was added
It keeps compatible with existing code.
As to the concerns about GC, it's caller's responsibility to keep callbacks and user data on the stack, and free them after usage.
Let me know if you have any questions.