-
Thanks @headius and the team for JNR-FFI. It's an awesome tool. I am trying to replicate a snippet from StackOverflow, slightly simplified. char* buffer = NULL;
size_t bufferSize = 0;
FILE* myStream = open_memstream(&buffer, &bufferSize);
fprintf(myStream, "You can output anything to myStream, just as you can with stdout.\n");
fclose(myStream); //This will set buffer and bufferSize.
printf("I can do anything with the resulting string now. It is: \"%s\"\n", buffer);
free(buffer); The best I could get to was this: public interface LibC {
Pointer open_memstream(Pointer stringPtr, Pointer sizePtr);
int fprintf(Pointer stream, String str);
int fclose(Pointer stream);
}
public static void main(String[] args) {
LibC libc = LibraryLoader.create(LibC.class).load("c");
Pointer buffer = Memory.allocate(Runtime.getSystemRuntime(), NativeType.UCHAR);
Pointer bufferSize = Memory.allocate(Runtime.getRuntime(libc), Integer.BYTES);
Pointer myStream = libc.open_memstream(buffer, bufferSize);
libc.fprintf(myStream, "This is a test");
libc.fclose(myStream);
int size = bufferSize.getInt(0);
System.out.printf("Size = %d%n", size);
String s = buffer.getString(0);
System.out.printf("String = %n%s%n", s);
} I believe I'm doing something wrong in my conversion from I've read the docs and scoured through source code, but can't figure out how to do this correctly. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Found a solution: Updated C code for clarity. #include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
char* buffer = NULL;
size_t bufferSize = 0;
FILE* myStream = open_memstream(&buffer, &bufferSize);
fprintf(myStream, "This is a test");
fclose(myStream);
printf("Size = %d\n", bufferSize);
printf("String = %s\n", buffer);
free(buffer);
} Output from C program:
Matching Java JNR-FFI code: public interface LibC {
Pointer open_memstream(Pointer stringPtr, Pointer sizePtr);
int fprintf(Pointer stream, String str);
int fclose(Pointer stream);
void free(Pointer pointer);
}
public static void main(String[] args) {
LibC libc = LibraryLoader.create(LibC.class).load("c");
Pointer bufferAddress = Memory.allocateDirect(Runtime.getRuntime(libc), Long.BYTES);
Pointer bufferSize = Memory.allocateDirect(Runtime.getRuntime(libc), Integer.BYTES);
Pointer myStream = libc.open_memstream(bufferAddress, bufferSize);
libc.fprintf(myStream, "This is a test");
libc.fclose(myStream);
int size = bufferSize.getInt(0);
System.out.printf("Size = %d%n", size);
Pointer buffer = Pointer.wrap(Runtime.getRuntime(libc), bufferAddress.getLong(0));
String s = buffer.getString(0);
System.out.printf("String = %s%n", s);
libc.free(buffer);
} Output from Java:
|
Beta Was this translation helpful? Give feedback.
-
Thanks for working through this yourself! I missed the original post but it looks like you came up with a good solution. Do you have any suggestions for improving the API to make this more obvious? Your example might also be good to add to our examples repository or the wiki. |
Beta Was this translation helpful? Give feedback.
-
The current API is very good. What I struggled with was trying to understand which JNR equivalents would be the most suitable equivalent for a given C snippet. The existing code samples are useful, but it's not easy to understand the relationship with the original C implementation. I think having a comprehensive set of simple, side-by-side C/JNR examples would really go a long way to help developers understand the great power and possibilities that JNR opens. Thanks again @headius and the team! PS: even though Project Panama's CLinker API is trying to do the same thing, I like JNR's API more. Once you get the hang of it, it's easier to see the intent of the original C code, so porting from C to Java becomes more natural. |
Beta Was this translation helpful? Give feedback.
Found a solution:
Updated C code for clarity.
Output from C program:
Matching Java JNR-FFI code: