Languages and Scripting
cancel
Showing results for 
Search instead for 
Did you mean: 

pointer to incomplete class type is not allowed with JNI

 
SOLVED
Go to solution
Paul Kupperman
Occasional Advisor

pointer to incomplete class type is not allowed with JNI

First - I'm a C expert, not a C++ or Java programmer, so I'm not as familiar with this subject as I would like to be for this.
I am trying to create a shared object to access my company's java application from C++. We have the (working) code to do it on Windows, and I've been trying to get it to compile on our Itanium box. The compiler version is:
aCC: HP aC++/ANSI C B3910B A.06.10 [Mar 22 2006]

I've had to add 'struct' on the declarations for several structure variables in the code. Without them I get "xxx not defined" errors. Once I fixed that I started getting "pointer to incomplete class type is not allowed" errors every place we try to access a structure defined as "extern struct JNIEnv* env". An example of the problem code is:
env->DeleteLocalRef(jlocal);

Researching the error I find a lot of info about not being able to use "xx->" for structures that have a forward declaration, but even though JNIEnv has one in jni.h, it is immediately followed by a complete declaration.

I found a spot where someone fixed a similar problem by removing 'struct' from the variable declaration, but then I get errors about it not being a structure. I would greatly appreciate any help.
Paul
11 REPLIES 11
Dennis Handly
Acclaimed Contributor

Re: pointer to incomplete class type is not allowed with JNI

>The compiler version is: A.06.10 Mar 22 2006

(The latest is A.06.25.02.)

>I've had to add 'struct' on the declarations for several structure variables in the code.

Don't do that. You need to include the proper headers and then it should work.

>I started getting "pointer to incomplete class type is not allowed" errors
env->DeleteLocalRef(jlocal);

To call class member functions you must first have a definition of your class visible.

>but even though JNIEnv has one in jni.h, it is immediately followed by a complete declaration.

Has one what, followed by what?
Showing a fragment or attaching the whole file will help.

Does jni.h have the definition of JNIEnv that includes DeleteLocalRef? Are you including that file before you are trying to access that class?
Paul Kupperman
Occasional Advisor

Re: pointer to incomplete class type is not allowed with JNI

>>I've had to add 'struct' on the declarations >>for several structure variables in the code.
>Don't do that. You need to include the proper >headers and then it should work.
As far as I can tell, the proper headers *are* included. For example, I have a structure 'Location' defined in struct.h, and struct.h is included in Int.cpp. A line after that include is:

void MarshallLocationResult(jobject jlocation, Location* loc);

I get <"Int.cpp", line 31: error #2020: identifier "Location" is undefined.> If I change the line to

void MarshallLocationResult(jobject jlocation, struct Location* loc);

the error goes away.


>>but even though JNIEnv has one in jni.h, it >>is immediately followed by a complete >>declaration.
>Has one what, followed by what?
Sorry - a forward declaration, followed by a complete declaration. Here is a fragment of jni.env (__cplusplus is *not* defined - defining it adds a whole host of new errors):

--------------------------------------------
struct JNINativeInterface_;

struct JNIEnv_;

#ifdef __cplusplus
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv;
#endif

/*
* JNI Invocation Interface.
*/

struct JNIInvokeInterface_;

struct JavaVM_;

#ifdef __cplusplus
typedef JavaVM_ JavaVM;
#else
typedef const struct JNIInvokeInterface_ *JavaVM;
#endif

struct JNINativeInterface_ {
void *reserved0;

--------------------------------------------
(If I'm following this correctly, we have forward declarations for JNINativeInterface_ and JNIEnv_, then a typedef of JNIEnv to be a pointer to JNINativeInterface_, and then a complete definition of JNINativeInterface_, which should lead to a complete definition of JNIEnv. A thought hits me as I type - is the typedef of JNIEnv to the forward declaration the problem? Maybe the typedef has to come after the full declaration?)

One of my include files has the line

extern struct JNIEnv* env;

in it (I had to add the 'struct' or we got the "I don't know what that is" error). That include file is after jni.h is included in my cpp file. A line like:

jobject jlocal = env->NewObject(jniLocator.classRef, jniLocator.ctor, dbID);

in the cpp following both includes gets <"Int.cpp", line 81: error #2393: pointer to incomplete class type is not allowed>

Researching the error says I found it info saying that meant it was using a forward declaration. There is one, but it also has a complete declaration, that I would have thought would be what actually is used.

Thanks,
Paul
Dennis Handly
Acclaimed Contributor

Re: pointer to incomplete class type is not allowed with JNI

>As far as I can tell, the proper headers *are* included. For example, I have a structure 'Location' defined in struct.h, and struct.h is included in Int.cpp. A line after that include is:
void MarshallLocationResult(jobject jlocation, Location* loc);
>I get <"Int.cpp", line 31: error #2020: identifier "Location" is undefined.>

This can't happen if Location is defined in struct.h and that is included.

Please compile with "-E -.i" and attach the generated .i file.

>__cplusplus is *not* defined - defining it adds a whole host of new errors):

__cplusplus IS defined by the compiler.

>which should lead to a complete definition of JNIEnv.

Yes later on with struct JNIEnv_ { ...

>is the typedef of JNIEnv to the forward declaration the problem?

No, the compiler should follow it to the definition.
Paul Kupperman
Occasional Advisor

Re: pointer to incomplete class type is not allowed with JNI

> >As far as I can tell, the proper headers *are* included. For example, I have a structure 'Location' defined in struct.h, and struct.h is included in Int.cpp. A line after that include is:

>>void MarshallLocationResult(jobject jlocation, Location* loc);

>>I get <"Int.cpp", line 31: error #2020: identifier "Location" is undefined.>
>This can't happen if Location is defined in struct.h and that is included.
Apparently it can, because Location is defined in struct.h, and struct.h is included. From a 'C' point of view, it should work. Not sure why it can't see the definition.

>Please compile with "-E -.i" and attach the >generated .i file.
Attached.

>>__cplusplus is *not* defined - defining it adds a whole host of new errors):
>__cplusplus IS defined by the compiler.
It's not at least inside the .h files. I added garbage inside one of the ifdef blocks, and the compiler doesn't see it:

#ifdef __cplusplus
jklfdsajklfdsjkfdl;sjkfdsla;
extern "C" {
#endif

Compiles without showing that it's tried to read the junk line.

>>which should lead to a complete definition of JNIEnv.
>Yes later on with struct JNIEnv_ { ...
That's how I thought it should work.

>>is the typedef of JNIEnv to the forward declaration the problem?
>No, the compiler should follow it to the definition.
Again, that's how I thought it should work.

Thanks,
Paul
Dennis Handly
Acclaimed Contributor

Re: pointer to incomplete class type is not allowed with JNI

>Apparently it can, because Location is defined in struct.h, and struct.h is included. From a 'C' point of view, it should work.

Not from a legal C++ program. The whole problem occurs because __cplusplus is illegally undefined.

>Attached.

Unfortunately this doesn't help with macro debugging. You'll need to search for "#undef __cplusplus" or if not obvious, use this option:
aCC ... -Wc,-L,Int.out

Then search Int.out for __cplusplus.

>It's not at least inside the .h files. I added garbage inside one of the ifdef blocks, and the compiler doesn't see it:

Ok, somebody undefined it sooner. If not obvious, look at Int.out.
Paul Kupperman
Occasional Advisor

Re: pointer to incomplete class type is not allowed with JNI

If I add "#define __cplusplus" at the beginning of my cpp file, I get the following errors:

"/usr/include/sys/_fd_macros.h", line 102: error #2040: expected an identifier
extern "C" {
^

"/usr/include/sys/_fd_macros.h", line 102: error #2065: expected a ";"
extern "C" {
^

"/usr/include/sys/types.h", line 465: error #2040: expected an identifier
extern "C" {
^

(the carets are supposed to be under the opening curly brackets, the formatting here changes their location)

The files aren't that big. I've attached a zip with the original (works on Windows) source. The "unsigned char" variables have been substituted for the Windows 'bool' type that doesn't exist on the Itanium.

Thanks!
Paul
Dennis Handly
Acclaimed Contributor

Re: pointer to incomplete class type is not allowed with JNI

What does your compile line look like?

>substituted for the Windows 'bool' type that doesn't exist on the Itanium.

bool only exists in C++, not C, which has _Bool.
Paul Kupperman
Occasional Advisor

Re: pointer to incomplete class type is not allowed with JNI

CFLAGS="-c +DD64 -Ae +z +W4232 -I/opt/java1.5/include -I/opt/java1.5/include/hp-ux"
DEFINES="-D_USRDLL -DEZGEOINT_EXPORTS -DHPIT64"
#aCC ${CFLAGS} ${DEFINES} EZGeoInt.cpp -o EZGeoInt.o
aCC ${CFLAGS} ${DEFINES} EZGeoJNI.cpp -o EZGeoJNI.o

#ld -o libEZGeo.so EZGeoInt.o EZGeoJNI.o -b


>>substituted for the Windows 'bool' type that doesn't exist on the Itanium.
>bool only exists in C++, not C, which has _Bool.

I thought this was C++ - is that not what the aCC compiler does?

Thanks!
Dennis Handly
Acclaimed Contributor
Solution

Re: pointer to incomplete class type is not allowed with JNI

>CFLAGS="-c +DD64 -Ae +z +W4232 ..."

Here is your problem. You are using CFLAGS instead of the more standard CXXFLAGS.
And in particular that -Ae says to switch to C mode.

>I thought this was C++ - is that not what the aCC compiler does?

It also does C89 and C99.

>ld -o libEZGeo.so -b ...

You shouldn't be using ld directly to create shlibs. Instead use "aCC -b".