idiomatic JNA to handle C string allocated in native code

394 views
Skip to first unread message

Kyle Hayes

unread,
Oct 30, 2020, 11:52:29 PM10/30/20
to Java Native Access

I am wrapping native code that returns an allocated C string.   The string is allocated with malloc() inside the native code.  I want to convert the string to a Java string and then make sure that the C string is freed so that I do not leak memory.   The C function returns a simple char * value.

What is the most idiomatic way to do this in JNA?   Note that due to the C API, I need the Java code to take ownership of the C string and deleted it as soon as it is converted to a Java string.  The string is in ASCII, not even UTF8.

I am already wrapping another API call that returns a const string from the C code.  Ownership there is with the C library (static strings) so there is nothing to free.  The default translation works great in that case.   The C API call there returns const char*.

Thanks for any pointers.

Best,
Kyle

Daniel Widdis

unread,
Oct 31, 2020, 12:04:20 AM10/31/20
to jna-...@googlegroups.com

Generally if the native API has a function that allocates memory, the native API also has a function that releases the memory.  I don’t think there’s any way (idiomatic or not) to release memory from Java via JNA if it was allocated inside the native code.

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/9aa58aa3-5af9-42d6-9106-042c98882a82n%40googlegroups.com.

Matthias Bläsing

unread,
Oct 31, 2020, 5:01:28 AM10/31/20
to jna-...@googlegroups.com
Hi Kyle,
I would wrap such a case so that the wrapper returns a plain "com.sun.jna.Pointer". That can be used to acess the string and can be used to free it.

The relevant functions are:

  • com.sun.jna.Pointer#getString to fetch the value
  • com.sun.jna.Pointer#nativeValue to convert from Pointer to long memory address (this is static and is invoked with the Pointer as an argument)
  • com.sun.jna.Native#free to free the memory

In the JNA codebase such an API would have an abstract companion class "<Interface>Util", that does the unwrapping.

Greetings

Matthias


Kyle Hayes

unread,
Oct 31, 2020, 10:53:27 AM10/31/20
to Java Native Access

Hi Matthias,

See below...

Oh!  OK.  Can I just declare the native function as returning a Pointer?

static private native Pointer plc_tag_get_string(int tag_id, int string_offset);

And then I wrap it:

public String getString(int stringOffset) {
    // error handling omitted
    Pointer rawPointer = plc_tag_get_string(this.id, stringOffset);
    String result = rawPointer.getString();
    Native.free(rawPointer);
    return result;
}

Something like that?

Thanks so much.  I had not looked at raw pointer values like this.

Best,
Kyle


Matthias Bläsing

unread,
Oct 31, 2020, 3:44:11 PM10/31/20
to jna-...@googlegroups.com
Hi Kyle,

Am Samstag, den 31.10.2020, 07:53 -0700 schrieb Kyle Hayes:
> > [Function returning char* that needs freeing]
>
> Oh!  OK.  Can I just declare the native function as returning a
> Pointer?
>
> static private native Pointer plc_tag_get_string(int tag_id, int
> string_offset);
>
> And then I wrap it:
>
> public String getString(int stringOffset) {
>     // error handling omitted
>     Pointer rawPointer = plc_tag_get_string(this.id, stringOffset);
>     String result = rawPointer.getString();
>     Native.free(rawPointer);
>     return result;
> }
>
> Something like that?
>
> Thanks so much.  I had not looked at raw pointer values like this.

that should work in principle. The free should be:

Native.free(Pointer.nativeValue(rawPointer))

Greetings

Matthias

Kyle Hayes

unread,
Nov 4, 2020, 10:00:59 AM11/4/20
to Java Native Access
Thanks, Matthias.

I will try this out.

Best,
Kyle
Reply all
Reply to author
Forward
0 new messages