-
Notifications
You must be signed in to change notification settings - Fork 587
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
@ByPtrPtr
array argument for const
pointer needs to be copied back from native call results
#776
Comments
…* const`s. This fixes bytedeco#776 Before this change, we did not copy array contents back to the argument array for "const **" as it is regarded as immutable. But it in fact it mutable. This StackOverflow question describes it well. https://stackoverflow.com/questions/4949254/const-char-const-versus-const-char After this change, it will avoid copying if the parameter pointer itself is const.
From what I understand of how libremidi_midi_out_port() works, the pointer of "name" itself gets returned, and since that is not memory allocated by the JVM, the mode flag has no effect anyway so that won't help: |
JNI
here I created the PR as I confirmed that the change brought in the expected result with |
It might work with your version of the JDK, but it's not part of the JNI specs. Anyway, in the worst case it gets ignored, so could you make your change additive, such that JNI_ABORT does not get used for any case that it is not currently being used for? |
I also doubt that passing to Anyway, you don't want to copy the data pointed by the new pointer to the Java array, do you ? We don't even know its length: it can differ from the original Java array. So the question for me is whether something must be changed in JavaCPP. |
@HGuillemet you're right on that JVM does not know the exact size of buffer. It does not apply to this case, (edit) but As long as Ragardless, I am all for the right implementation. My understanding as of now is that (1) current implementation is wrong in that it is copying the buffer back to |
Right. The following code, without infomap, causes a segmentation fault: void libcall(char** name) {
*name =NULL;
} byte[] b = new byte[] { 18 };
libcall(b);
System.out.println(b[0]); While the same code with static const char* a = "a";
void libcall(char** name) {
*name = (char *) a;
} byte[] b = new byte[] { 18, 19, 20, 21 };
libcall(b);
System.out.println(b[0]); Also aborts and doesn't print 96: the new pointer is not copied back. |
So, if I understand correctly, the changes in pull #777 would make it crash not only in the char** case, but also in the const char** case. What's the point of those changes? |
If I understand correctly, the latest consequence is that current code (without my change) is already problematic depending on how the invoked native code behaves (updates the pointer, with short buffer than the length of array). I left my PR open only because depending on the consequence it might be useful to update the change. |
I think the right logic would be to prevent the generator to generate the overloads that use primitive arrays or buffers when the C++ function can change the value of a pointer in the chain of indirections. And, if the overloads are generated, the JNI_ABORT should be used iif the char themselves cannot be change by the library, as @atsushieno pointed out, for instance |
Ok, sounds alright, please approve pull #777 if it looks good, thanks! |
Yes. I would find it best if we can still optionally generate those extra methods if a binding author specifies some annotation in the mappings. But that should be documented, and actually how the array -like mappings work are currently not documented. We (binding developers) would have no idea on how things work and what we are not supposed to do with those generated methods (like, I was told to not do this only on this issue). |
Oh, no, let's not approve #777 as is, that's not what we want. |
There are a lot of things that are just mechanically generated with no guarantees to work. Contributions are welcome! |
So we don't try to implement the first part of my last message ? Or do you see an easy way to do it ? |
Sure, that sounds good. |
I have been trying to build a JavaCPP binding for libremidi, and had been failing to bind this function:
The implementation for this function assigns the actual pointer to the string into
name
.Now, when I tried to use the binding (I could manage to build it with some mappings) via
byte[]
(excuse my Kotlin code):it failed to get the expected string. It did work when I made changes to the code to use
BytePointer
though:The thing is that the pointee string at
const char** name
can be modified, and when we passbyte[]
that needs to be copied back to the binding parameter. It seems that JavaCPP works if the C function argument werechar**
.The cause of the problem is at
Generator.parametersAfter()
:The resulting generated code (
jnilibremidi.cpp
), especially forlibremidi_midi_out_port_name()
withbyte[]
, looks like this.This assumes that the
const char **
argument must be used only as an input and not to alter the output. But that's not correct. It would be true only if it isconst char * const *
. This StackOverflow question describes it well, namely:It is implemented for some optimization, but to ensure the implementation correctness the copying condition at
parametersAfter()
should rather be like:I will create a PR based on this suggestion.
The text was updated successfully, but these errors were encountered: