I am looking to be able to execute code from a Java project inside an Excel VBA sheet. Elsewhere on SO, I have discovered IKVM, which is a .NET implementation of Java which allows converting a .jar into a .dll. I was hoping this would let me access the classes/methods from the .jar inside the VBA editor, but I am having trouble doing so.
I have tried using the declare statement in VBA (in many different permutations, attempting to make it work) but the most common error refers to entry points in the .DLL.
I have also tried registering the .DLL as a reference in Excel, but it gives a boilerplate error and does not register it.
As a reference, I've been testing it using the following class before bothering to test it with the whole project:
public class IKVMTest {
public static void print(String s) {
System.out.println(s);
}
}
This class is compiled by Eclipse and exported into IKVMTest.jar. At this point, I use ikvmc -target:library IKVMTest.jar to receive IKVMTest.dll. For simplicity's sake, this .dll and the Excel sheet I am testing in are dumped in the IKVM bin folder (since there are some dependencies on the IKVM .dll files).
If I could get it working for this sample test, I could get it working for the project overall.
Have you tried making your .NET assembly COM visible so you can use VBA to instantiate it?
using [ComVisible(true)] on the class and methods generated by the IKVM code might make it visible as a COM object to your VBA app.
Have a look here for reference: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.comvisibleattribute.aspx#Y1600
Also, have a look here: How to call a .net assembly in VBA using COM Interop
http://blogs.msdn.com/b/smondal/archive/2009/08/31/how-to-call-a-net-assembly-in-vba-using-com-interop.aspx
Related
I am working on a system where I am using part of the JOGL OpenGL bindings to Java. I find the basic idea behing the "gluegen" C to Java binding generator good but the docs are thin and I havn't been able to locate a simple sample of gluegen usage consisting of:
A C module the does something like modify a string or print a string to stdout (ie: easily tested from java code) an expanded version one with multiple methods that handle each data type handled by gluegen.
the appropriate "cfg", ".h" files needed to power gluegen for the sample source.
A build script - ideally simple not factored out too much into an endless chain to follow generic makefile or shell script :)
the result of running the build script gives you the generated and sample code for a complete native side DLL with DLL main, export tables, and whatever else is needed to load into java on a windows box (.lib for unix)
A C compile of the code with MSVC and/or GCC to compile and link the code and generated code to produce the DLL.
The generated java class or classes that mate with the DLL including initialization.
In a sense sort of a "hello world" in C to be called from Java as a place to start.
PK
I'm trying for a while to use a library in java that I found a few months ago for edit packets.
The library is "like" jnetpcap but much richer, and most important seems to be newer and less buggy...
Here is the open source homepage of the project:
https://code.google.com/p/netutils/downloads/detail?name=netutils_toturial.pdf&can=2&q=
In the manual the person who wrote this library said we need to use "libnet.lib" and "netutils.dll" files.
I'm not really sure how to make it work, it seems to have a problam with the "netutils.dll" when trying to run a simple code.
Hope to get an answer from someone. Thanks a-lot.
From the pdf documentation:
The java library calls C code using java JNI (Java Native Interface).
The C code is compiled into two shared libraries (Linux) or dll’s
(Windows). The dynamic libraries should be placed in the java
java.library.path (path where the JVM searches for dynamic libraries).
There are two options for placing the libraries:
1. Putting the libraries in one of the default path’s.
2. Put the library anywhere and add the path to the java.library.path as shown:
java -Djava.library.path=place.....
Have you tried any of these options?
For point 1 you can use the following code, as reported in the dock to detect which is your java.library.path:
public class ShowJavaLibraryPath {
public static void main(String [] args) {
System.out.println(System.getProperty(”java.library.path”));
}
}
If you prefer the point 2, just add the .dll where you prefer and add the option -Djava.library.path=folder_you_choose to the Run Configuration arguments.
I have seen a few posts on this, but I haven't seen any solutions so far. I have a .jar file that I'm converting to a .NET DLL via IKVM. I'm trying to figure out how to make the methods in the DLL available inside the excel VBA environment. here are the details.
1.) installed IKVM & registered it's DLL's to GAC
2.) ran IKVM to create the a .net .dll (mytest.dll)
ikvmc mytest.jar
3.) registered the new .dll
regasm mytest.dll
4.) From here i created a VB.NET project and added mytest.dll and IKVM.OpenJDK.Core.dll as references to the project. I am then able to access the methods within the .dll in .NET. This is great!
5.) what I really want to do is be able to use the .dll in VBA as well. Initially vba wouldn't accept the .dll directly as it's a .net library. I attempted to create a type library:
regasm /codebase /tlb mytest.dll
This created a .tlb file which is nice, but it did throw a warning about the library not being strongly named.
6.) then I loaded the .tlb as a reference in my vba editor. This works, however when I try to access the methods nothing shows up. Similarly if I look in the object viewer for my library i can see my two classes but not the members of those classes.
Additionally, I imagine that I probably also need to somehow reference the IKVM.OpenJDK.Core.dll inside VBA as well. However I can't do that either since it's a .NET .dll.
Has anyone had success converting a .jar file into something that can be used with VBA?
I think you always need to explicitly mark a class to be usable via COM interop. Here's an example of a Java class that is usable from VBA:
import cli.System.Runtime.InteropServices.*;
#ClassInterfaceAttribute.Annotation(ClassInterfaceType.__Enum.AutoDual)
public class SampleWidget {
public int Add(int x, int y) {
return x + y;
}
}
Here are the steps to compile:
Copy IKVM.Runtime.dll and all IKVM.OpenJDK.*.dll into the current directory or the GAC.
Run "ikvmstub mscorlib" to generate mscorlib.jar.
Create a Java source named SampleWidget.java containing the code above.
javac -cp mscorlib.jar;. SampleWidget.java
ikvmc -out:SampleLibrary.dll SampleWidget.class -r:mscorlib.dll
tlbexp SampleLibrary.dll
regasm /codebase SampleLibrary.dll (this step needs administrator rights)
Now you can add a reference to the SampleLibrary.tlb from VBA and use the SampleWidget class.
I've found several instructions on how to import user-built .class and .jar files to JPype, but I seem to be having a lot of trouble getting anything working at all.
What works: I can import standard java stuff and print HELLO WORLD and such.
Some of what I've tried:
I've tried adding -Djava.class.path with the path to a jar containing the relevant class files, to a directory structure containing (several folders down) the relevant .class files, as well as '-Djava.ext.dirs'. I've recompiled and re-installed with a different JVM location. The class I am attempting to instantiate is Outer, public, and has a public constructor.
I'm using Python 2.6.1 on OSX 10.6.
My current test file:
from jpype import *
startJVM(getDefaultJVMPath(), '-Djava.class.path=/Users/gestalt/Documents/msmexplorer_git/msmexplorer/MSMExplorer/build/classes')
java.lang.System.out.println("hello world")
msmexplorer = JPackage('org.joofee.meh.msmexplorer')
T = msmexplorer.MSMExplorer()
shutdownJVM()
If I use JClass I always get ClassNotFound exceptions from JPype; if I use JPackage I get Package not callable errors. Basically, JPype can't find my stuff.
Thanks so much!
EDIT (possibly helpful debugging stuff...):
Is there a straightforward way to print which third party java classes are available/imported?
Package not callable errors are referenced in this link) it would seem you need to make sure the java class file is accessible from the working directory. I am not sure how the jvm classpath comes into play, I would have thought how you did it would work.
You could also try loading the org package and then getting to the other packages through that one as the link I shared shows:
msmexplorer = JPackage('org').joofee.meh.msmexplorer
T = msmexplorer.MSMExplorer()
My first attempt at jython is a java/jython project I'm writing in eclipse with pydev.
I created a java project and then made it a pydev project by the RightClick project >> pydev >> set as... you get the idea. I then added two source folders, one for java and one for jython, and each source folder has a package. And I set each folder as a buildpath for the project. I guess I'm letting you know all this so hopefully you can tell me wether or not I set the project up correctly.
But the real question is: how do I get my jython code made into a class file so the java code can use it? The preferred method would be that eclipse/pydev would do this for me automatically, but I can't figure it out. Something mentioned in the jython users guide implies that it's possible but I can't find info on it anywhere.
EDIT: I did find some information here and here, but things are not going too smooth.
I've been following the guide in the second link pretty closely but I can't figure out how to get jythonc to make a constructor for my python class.
Jythonc doesn't exist anymore, it has been forked off to another project called Clamp, but with that said...
...you can pre-compile
your python scripts to .class files
using:
jython [jython home]/Lib/compileall.py
[the directory where you keep your
python code]
Source - Jython Newsletter, March 2009
When I fed it a folder with Python 2.7 code (knowing it would fail in Jython 2.5) it did output a .class file, even though it doesn't function. Try that with your Jython scripts. If it works, please let us know, because I'll be where you are soon enough.
Once you're that far, it isn't hard to convert your command line statement to an External Tool in PyDev that can be called as needed.
Following the "Accessing Jython from Java Without Using jythonc" tutorial it became possible to use the jython modules inside java code. The only tricky point is that the *.py modules do not get compiled to *.class files. So it turns out to be exotic scripting inside java. The performance may of course degrade vs jythonc'ed py modules, but as I got from the jython community pages they are not going to support jythonc (and in fact have already dropped it in jython2.5.1).
So if you decide to follow non-jythonc approach, the above tutorial is perfect. I had to modify the JythonFactory.java code a bit:
String objectDef = "=" + javaClassName + "(your_constructor_params here)";
try {
Class JavaInterface = Class.forName(interfaceName);
System.out.println("JavaInterface=" + JavaInterface);
javaInt =
interpreter.get("instance name of a jython class from jython main function").__tojava__(JavaInterface);
} catch (ClassNotFoundException ex) {
ex.printStackTrace(); // Add logging here
}