JNI: Signedness with GetStringUTFChars() and ReleaseStringUTFChars()

P

Peter

I'm working through Sheng Liang's "The JNI Programmer's Guide and
Specification", and am on chapter 3, working the "Prompt" example. I'm
working through all the examples using gcc on GNU/Linux and VC++ on MS
Windows. Here's the C code in Sheng's book:


#include <stdio.h>
#include "Prompt.h"

JNIEXPORT jstring JNICALL
Java_Prompt_getLine( JNIEnv *env, jobject obj, jstring prompt )
{
char buf[128];
const jbyte *str;

str = (*env)->GetStringUTFChars( env, prompt, NULL );
if ( str == NULL ) return NULL;

printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);

scanf("%s", buf);
return (*env)->NewStringUTF(env, buf);
}


When I compile this with gcc, I get the warnings:

Prompt.c: In function Java_Prompt_getLine() Prompt.c:16: warning: pointer
targets in assignment differ in signedness

Prompt.c:20: warning: pointer targets in passing argument 3 of
(*env)->ReleaseStringUTFChars() differ in signedness

The code to focus on here is:

const jbyte *str;
str = (*env)->GetStringUTFChars( env, prompt, NULL );
(*env)->ReleaseStringUTFChars(env, prompt, str);

Looking into jni.h:

const char* (JNICALL *GetStringUTFChars)
(JNIEnv *env, jstring str, jboolean *isCopy);

void (JNICALL *ReleaseStringUTFChars)
(JNIEnv *env, jstring str, const char* chars);


And from linux/jni_md.h:

typedef signed char jbyte;



Doing some Googling, it appears that the C standard allows char to be either
signed or unsigned by default. Using a small test program where I set a char
variable equal to 255, it appears that with gcc on GNU/Linux, a char by
default is signed.

So I don't see the problem here.

* GetStringUTRChars() returns a ptr to a signed char.
* The 3rd arg of ReleaseStringUTFChars() takes a ptr to a signed char.
* A jbyte is a signed char


So what exactly is gcc complaining about?

Thanks for reading down this far. :)

Pete
 
G

Gordon Beaton

When I compile this with gcc, I get the warnings:

Prompt.c: In function Java_Prompt_getLine() Prompt.c:16: warning: pointer
targets in assignment differ in signedness

Prompt.c:20: warning: pointer targets in passing argument 3 of
(*env)->ReleaseStringUTFChars() differ in signedness
[...]

* GetStringUTRChars() returns a ptr to a signed char.
* The 3rd arg of ReleaseStringUTFChars() takes a ptr to a signed char.
* A jbyte is a signed char

So what exactly is gcc complaining about?

According to the gcc documentation, the type "char" is distinct from
both "signed char" and "unsigned char", even though its behaviour is
always identical to one of them.

Various alternative solutions are:

- declare your variables so the sign agrees
- don't use -pedantic if that's what you're doing
- turn off the specific warning with -Wno-pointer-sign
- use a cast
- ignore the warning

/gordon
 
C

Chris Uppal

Peter said:
* GetStringUTRChars() returns a ptr to a signed char.
* The 3rd arg of ReleaseStringUTFChars() takes a ptr to a signed char.
* A jbyte is a signed char


So what exactly is gcc complaining about?

I think it's probably about GNU's ultra precise (and legitimately so)
interpretation of what 'char' means in C (or C++). There are /three/ possible
signednesses for a char -- default (i.e. unspecified, which is what you get if
you have just 'char'), explicitly signed, and explicitly unsigned. GCC will
moan if you implicitly convert between any of the three.

Broadly speaking, in this context, the warnings can be ignored.

-- chris
 
D

Dale King

Peter said:
I'm working through Sheng Liang's "The JNI Programmer's Guide and
Specification", and am on chapter 3, working the "Prompt" example. I'm
working through all the examples using gcc on GNU/Linux and VC++ on MS
Windows. Here's the C code in Sheng's book:
[snip]

The code to focus on here is:

const jbyte *str;
str = (*env)->GetStringUTFChars( env, prompt, NULL );

Looking into jni.h:

const char* (JNICALL *GetStringUTFChars)
(JNIEnv *env, jstring str, jboolean *isCopy);

void (JNICALL *ReleaseStringUTFChars)
(JNIEnv *env, jstring str, const char* chars);

So what exactly is gcc complaining about?

Gordon and Chris explained why gcc is complaining, but the real problem
is that str was declared to be of type const jbyte *. It should be of
type const char * since that is the type for the functions.

If you download the examples from the web site
(http://java.sun.com/docs/books/jni/) you will see that they did in fact
make this correction.

So I would suggest relying on the downloadable example code which can be
updated instead of the text of the book, which can not readily be revised:
 
P

Peter Jay Salzman

Dale King said:
Peter said:
I'm working through Sheng Liang's "The JNI Programmer's Guide and
Specification", and am on chapter 3, working the "Prompt" example. I'm
working through all the examples using gcc on GNU/Linux and VC++ on MS
Windows. Here's the C code in Sheng's book:
[snip]

The code to focus on here is:

const jbyte *str;
str = (*env)->GetStringUTFChars( env, prompt, NULL );

Looking into jni.h:

const char* (JNICALL *GetStringUTFChars)
(JNIEnv *env, jstring str, jboolean *isCopy);

void (JNICALL *ReleaseStringUTFChars)
(JNIEnv *env, jstring str, const char* chars);

So what exactly is gcc complaining about?

Gordon and Chris explained why gcc is complaining, but the real problem
is that str was declared to be of type const jbyte *. It should be of
type const char * since that is the type for the functions.

If you download the examples from the web site
(http://java.sun.com/docs/books/jni/) you will see that they did in fact
make this correction.

So I would suggest relying on the downloadable example code which can be
updated instead of the text of the book, which can not readily be revised:

Thanks Gordon and Chris! And I learned something new about C to boot! I had
no idea that char was distinct from signed char. I'm really thankful for
your responses.

Also, Dale, thanks for the tip about the code change. I'm still a Java
newbie, but it seems like the prototypes for GetStringUTFChars() and
ReleaseStringUTFChars are broken -- they should probably be using "const
signed char *", rather than "const char *".

I've verified that on Linux and Windows with Sun Java, a jbyte is typedefed
from a "signed char".

Thanks all!
Pete
 
D

Dale King

Peter said:
Also, Dale, thanks for the tip about the code change. I'm still a Java
newbie, but it seems like the prototypes for GetStringUTFChars() and
ReleaseStringUTFChars are broken -- they should probably be using "const
signed char *", rather than "const char *".

I don't think signed or unsigned is more correct than another. I think
char is a better choice than signed char because the data is essentially
text for any characters that are in ASCII. It is likely that a user of
the UTF string will want to process it as text including possibly
printing it out. In that case there is benefit to it being char as there
will be API's that expect char.

The one thing that they definitely did get wrong (and I just filed a bug
report on) is the JNINativeMethod structure that is used as part of
RegisterNatives has 2 pointers to utf strings, but doesn't declare them
as pointers to const, so I have to do a const_cast in C++.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

JNI: C vs C++ 2
JNI 1
Error : JNI 3
need help with this JNI code 6
JNI- Problem with setObjectArrayElement 0
Problem with JNI and Tomcat 6
JNI and Web Services 3
JNI problem with GetStringUTFLength 6

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top