Hopefully silly problem with import

Put your problem here if it does not fit any of the other categories.

Hopefully silly problem with import

Postby francis » Mon Feb 11, 2008 3:52 pm

I've been using C2J http://tech.novosoft-us.com/product_c2j.jsp to convert C code to almost unreadable but compileable Java code.

All the generated classes inherit from c2jrt which is a compiled class in /programs/novosoft/c2j/bin/c2jruntime.zip. I put this file into the classpath (java build path) which is project wide NOT package wide.

For some reason I set it up so all the Android classes I wrote myself are in my own package biz.dialgenie.android.genie wherease the generated classes are in the default package.

If I move the generated classes to my package they can no longer find c2jrt. "import c2jruntime;" doesn't help, its a compiler error itself. I can see the classes in the zip file, but there's no obvious package name for an import statement.

So yes I can compile the generated classes in the default package, but then can't access from my own code in my package. As I mentioned above the classpath is project wide so its not a problem that the classpath is only set for one package.

Assuming somebody has a solution to this, is it philosophically good to keep my stuff in one package, and the generated stuff (from my C code) in another package?

I've attached c2jruntime.zip
Attachments
c2jruntime.zip
(145.39 KiB) Downloaded 139 times
francis
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sat Feb 09, 2008 6:33 am
Location: Germany

Top

Postby ollo » Wed Feb 13, 2008 3:54 pm

Hello francis,

When You want to use your own lib, you must copy it into the workspace :!:

For example, create an new folder "lib", and move the c2jruntime.zip (not unzip) into it.
Then add the folder to the build-path (Choose: add class folder). Now your Project should compile without warnings and should run in the emulator.

There is something strange, you are talking about
import c2jruntime;
, but there ist no folder structure in the c2jruntime.zip :?
FYI.: Normally the Java-Library-Format is .jar. But this should not be the Problem.

Regards,
Ollo
ollo
Freshman
Freshman
 
Posts: 8
Joined: Thu Nov 15, 2007 11:38 am

Didn't work I'm afraid

Postby francis » Thu Feb 14, 2008 8:47 am

I hope these screenshots explain the problem

Dgwrapper.java is the highest level generated java file and is in the package created for the project: biz.dialgenie.android.genie. You can see 3 errors: it cannot find dgmain, uigenie, or c2jrt. However you can see that we have the source code of dgmain and uigenie in the src(default package) and c2jrt compiled in c2jruntime.zip(default package)

DialGenieController however has no errors. Neither do any of the other generated files in the default package.

Image

The next screen shot moves dgwrapper.java into the default package. It no longer has a package statement at the top of the source fle.

Image

Now dgwrapper compiles without error, its able to find dgmain, uigenie, and c2jrt.

But DialGenieController has errors, it can’t find dgwrapper.

Basically anything in a named package cannot import anything from the default package, and everything in c2jruntime.zip is going into the default package.

Adding the lib directory containing both the zip archive, and the extracted classes as a class folder didn’t help. The classes are not visible in the lib directory, I’ve attached a screen shot to prove they really are there.

Putting everything in the default package doesn’t work either because the launch configuration refuses to launch an activity from the default package.

Image
francis
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sat Feb 09, 2008 6:33 am
Location: Germany

Re: Didn't work I'm afraid

Postby ollo » Thu Feb 14, 2008 10:31 am

Hello francis,

francis wrote:Basically anything in a named package cannot import anything from the default package, and everything in c2jruntime.zip is going into the default package.

This is an known problem. The easiest way get it running is :
  • Create an new Package, e.g. biz.dialgenie.android.genie.utils
  • Move the Classes from default into the new package : biz.dialgenie.android.genie.utils
  • Now you should press the wonder keys of eclipse : <Ctrl> + <shift> + o, OR create a new line under "package biz.dialgenie.android.genie" with the following content : import biz.dialgenie.android.genie.utils.*; by hand.

francis wrote:Adding the lib directory containing both the zip archive, and the extracted classes as a class folder didn’t help.

This is not the idea, I tried to tell you. You should only move the Zip file from C:\Programme\Novosoft\C2J\Bin ... into the new created folder lib of your DialGenie Project. Then you should edit the Build-Path of your Project:
  • Remove the current c2jruntime.zip
  • Use Add jar and select the zip file from DialGenie | lib | c2jruntime.zip
Now Eclipse find all the needed classes like before and the emulator, too.

francis wrote:The classes are not visible in the lib directory, I’ve attached a screen shot to prove they really are there.

The classes should not appear here. You should only see the .zip file, after you have copied it into the lib folder. After you have added the zip into the Build-path, it is still physically there, but not visible in eclipse. Like in the picture above, you can see all the classes under Referenced Libraries | c2jruntime.zip .

FYI: This could help to understand all the Basic Package, Project, Java-Eclipse-Stuff Good Online Java Book (Ger)

Regards,
Ollo
ollo
Freshman
Freshman
 
Posts: 8
Joined: Thu Nov 15, 2007 11:38 am

can't move library files to package

Postby francis » Thu Feb 14, 2008 5:34 pm

If I copy either c2jruntime.zip or its class contents into a lib directory in my project, and then “Add Class Folder” none of the classes are visible anywhere.

If I use “Add external JARs” to c2jruntime.zip its classes become visible but in the default (library) package. These can only be used by source code in the default (source) package.

I can create a new source package, but I can’t drag the c2j classes or the entire zip into this package. I cannot create a new library package.

It seems to be a fundamental rule of Java that classes in named packages cannot import from classes in default packages. Its probably even a good rule.

C2jruntime.zip was probably compiled before Java introduced the rule prohibiting importing from default. So there must be a way of defining a package for an archive of compiled classes.

Otherwise old compiled classes are useless for Android because it won’t let you have the launch activity in the default package.
francis
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sat Feb 09, 2008 6:33 am
Location: Germany

Re: can't move library files to package

Postby ollo » Thu Feb 14, 2008 6:49 pm

francis wrote:If I copy either c2jruntime.zip or its class contents into a lib directory in my project, and then “Add Class Folder” none of the classes are visible anywhere.
If I use “Add external JARs” to c2jruntime.zip its classes become visible but in the default (library) package. These can only be used by source code in the default (source) package.


This sounds very very strange. It doesn't matter if you use the Add Jar's or the Add External Jars Button.

francis wrote:I can create a new source package, but I can’t drag the c2j classes or the entire zip into this package. I cannot create a new library package.


You must create an Package (via the menu File | New | Package) [NOT a Source-Folder]
[align=center]This should look like this :
Image[/align]
Then there will appear an new package under biz.dialgenie.android.genie. Then you can move all the classes from default into the new package via drag & drop.

francis wrote:C2jruntime.zip was probably compiled before Java introduced the rule prohibiting importing from default. So there must be a way of defining a package for an archive of compiled classes.

This is a very strange idea, imho.
ollo
Freshman
Freshman
 
Posts: 8
Joined: Thu Nov 15, 2007 11:38 am

Top

New package

Postby francis » Thu Feb 14, 2008 8:44 pm

I cannot use "Add Jar" only "Add External Jar" to include c2jruntime.zip. I was differentiating this from "Add Class Folder" where it could not find the classes whether the class folder contained just the zip, or the extracted classes also.

I can certainly create a new package using the file menu, but its really not different from right clicking on the project and taking new.

It is created in the source menu, and the libraries cannot be dragged even to android.jar, let alone out of the referenced libraries domain and into the src domain.

Image

At the moment I can find no way eclipse allows me to define a package for already compiled classes, it refuses to allow me to reference these classes from code in a package, and android insists that the entry activity which is going to indirectly reference these classes be in a package.

All my reading says that the default package is there as a scratchpad, and its use is discouraged. So forcing classes in there, and not making it possible to define a package seems absurd, but thats the way it appears to be.
francis
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sat Feb 09, 2008 6:33 am
Location: Germany

Solution with 1.3 compliance

Postby francis » Fri Feb 15, 2008 9:26 am

The Java spec is clear that no class in a named package can import from the default package post compiler compliance 1.3

I think I have a solution. I created a new project with a default, and biz.dialgenie.android.c2jwrap packages. All the generated stuff went into default, and one class c2jwrapper that did nothing but extend dgwrapper in the named package.

I then set the Java compiler compliance to 1.3, and it all compiles. Created a jar from this project, and in my main project (compliance 6) I was able to reference the jar and import c2jwrapper from biz.dialgenie.android.c2jwrap.

I may not even need the jar file because packages in other projects also seem visible. Then my train arrived, so I’ve only got it to compile, not actually done anything yet.

I had to put c2jwrapper into a separate project because compiler compliance 1.3 does not allow you to launch an android application.

You also can’t use @SupressWarnings so I now have 100s of warnings. It’s a bit annoying that errors and warnings are reported on all projects in the workspace, not just the current project. I guess I’ll note the number of warnings and just check out new warnings.
francis
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sat Feb 09, 2008 6:33 am
Location: Germany

Solution with Reflection

Postby francis » Sun Mar 02, 2008 5:20 pm

The above didn't work

There is a workaround using reflection. Reflection is used to dynamically load classes, and their methods. Whether by accident or design, it is possible with reflection for a class in a named package to load a class in default package.

However dynamically loading each method would be cumbersome, and passing parameters and getting returns is very complicated. Everything has to be wrapped in Object classes. But classes in the default package can access classes in a named package.

cJavaWrapper is my generated wrapper class with many methods I want to access.

So my final solution was to declare an interface cJavaInterface in my package which declared all the methods in cJavaWrapper. In the default package I wrote a class cJavaBridge which implements cJavaInterface, and declares one extra static method: GetInterface

The other methods in cJavaBridge are non static, implement the interface, and simply call the appropriate method in cJavaWrapper

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class cJavaBridge implements cJavaInterface {
  3.  
  4.            public static cJavaInterface GetInterface() {
  5.  
  6.                    return new cJavaBridge();
  7.  
  8.            }
  9.  
  10.  
  11.  
  12.            public void GlobalsInit() {
  13.  
  14.                    cJavaWrapper.cGlobalsInit();
  15.  
  16.                    }
  17.  
  18.            
  19.  
  20.  
  21.  
  22.  
Parsed in 0.031 seconds, using GeSHi 1.0.8.4

GetInterface is used by DialGenieWrapper in the package to get an instance of the Interface, which can then be used as a normal class without using reflection further.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.         public DialGenieWrapper( ) {
  3.  
  4.                 Method GetInterface;
  5.  
  6.                
  7.  
  8.             try
  9.  
  10.                    {
  11.  
  12.                    GetInterface = Class.forName("cJavaBridge").getMethod("GetInterface", (Class [])null);
  13.  
  14.                    c2jBridge = (cJavaInterface)GetInterface.invoke( (Object[])null, (Object[])null );
  15.  
  16.                    } catch(Exception ex){
  17.  
  18.                         Assert.fail( ex.toString() );
  19.  
  20.                    }
  21.  
  22.  
  23.  
  24.                 c2jBridge.GlobalsInit();
  25.  
  26.         }
  27.  
  28.  
Parsed in 0.032 seconds, using GeSHi 1.0.8.4


The compiler forced me to catch some exceptions. I couldn’t figure out how to throw it on up, but assert works nicely. Class.forname() returns a Class object, and getMethod returns a Method in that Class. You can only call static methods through reflection.

Here are the definitions of the relfection methods.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. Class.getMethod(String name, Class[] parameterTypes)
  3.  
  4.  
  5.  
  6. Method.invoke(Object receiver, Object[] args)
  7.  
  8.  
Parsed in 0.033 seconds, using GeSHi 1.0.8.4
francis
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sat Feb 09, 2008 6:33 am
Location: Germany

Top

Return to Other Coding-Problems

Who is online

Users browsing this forum: Alexa [Bot] and 19 guests