I am trying to accessing dll methods in java which has been written in c#. From the following code i am trying to build dll which is generated successfully.
using System;
using Microsoft.Win32;
namespace CyberoamWinHelper
{
public class RegistryAccess
{
public static String getValue(String key)
{
RegistryKey rk = Registry.CurrentUser;
RegistryKey rk1=rk.OpenSubKey("Software\\Test", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl);
rk1.SetValue(key, "val1");
return rk1.GetValue(key).ToString();
}
public static void createSubkey(String name)
{
RegistryKey rk = Registry.CurrentUser;
rk.CreateSubKey("Software\\Test");
}
}
}
After this i am loading the generated dll in my java program code of which is as follows
public class JNI {
/**
* #param args the command line arguments
*/
public native String getValue(String key);
public static void main(String[] args) {
// TODO code application logic here
try
{
System.loadLibrary("CyberoamWinHelper");
JNI j=new JNI();
System.out.println(j.getValue("abc"));
}
catch(UnsatisfiedLinkError e)
{
System.out.println("Ex" + e.getMessage());
}
}
}
After running this code it is giving me the following error.
"Exjni.JNI.getValue(Ljava/lang/String;)Ljava/lang/String;"
Well i am not understanding what this error is saying but i want to solve it.
And one more question i am having is since the method i am calling is a static method will it be called in this way? i mean to call static method we need
"classname.methodname"
so here will it be able to call the method?
You can only call methods via JNI if those methods were in fact designed to be called this way. Your methods absolutely are not. What you're doing here has (sorry to be so blunt) absolutely no chance of ever succeeding -- it simply doesn't work this way.
There are several ways you might proceed. One would be to learn about JNI and how to write libraries that actually work with it. Here is the canonical reference for this. Doing this with C# adds yet another layer of complexity, though.
Another way would be to give up on JNI altogether and use a more appropriate mechanism to access the methods. You can learn about JNA here; it would be entirely better suited to your goals.
Try jni4net. From their web site. Some detailed explanation is here -> How calling from Java to .NET works in jni4net
Your use of JNI is incorrect. It's difficult (although not impossible) to use JNI with C# libraries. There is an excellent tutorial on how to go about it here. Doing a C# JNI search on google shall reveal more.
You should also investigate something like Grasshopper..
EDIT
http://caffeine.berlios.de/site/documentation/quickstart.html
is a cool solution.
Helpful site for you: http://www.sahirshah.com/java/jni.html
Try:
public class myJNI {
/**
* #param args the command line arguments
*/
public static native String getValue(String key);
static
{
System.loadLibrary("CyberoamWinHelper");
}
public static void main(String[] args) {
// TODO code application logic here
try
{
String myKey = "abc";
System.out.println(getValue(myKey));
}
catch(UnsatisfiedLinkError e)
{
System.out.println("Ex" + e.getMessage());
}
}
}
You need to wrap the dll in a c++ dll as described in the above link. Just generate a header file with the "javah -jni myJNI" command and build a c++ dll with the function signature found in that header file.
Have a look at : http://www.codeproject.com/KB/cross-platform/javacsharp.aspx for a specific "hello world" example in C#
Related
I'm making a game engine using LWJGL. The developer using it has to be able to use scripts. I decided to just make them use Java because writing an API in another language wasn't something I'm going to have the time nor experience to do. Anyways, I would have used x.main(); to run it, but The developer tells what the script is named, and that is stored in a variable. I just thought I could run a command to do that, using a method like exec() in python or eval() in JavaScript. I couldn't find a straightforward library that has this execution functionality.
To summarize this paragraph, I need a Java Library that can use a method like JavaScript's eval() or python's exec()
I dont know If I understood the problem, but I have focused on part of having "script name stored as variable" which sounds to me like a method name. You can invoke method by its name using reflections
public class MCAlu {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String scriptName = "sayHello";
Method scriptMethod = MyScript.class.getMethod(scriptName);
scriptMethod.invoke(null, null);
}
}
class MyScript {
public static void sayHello() {
System.out.println("Hi there!");
}
}
Since class has to be known and on the classpath (unless you will load it in the runtime), class name can be as well provided as string resulting in
String scriptClass="MyScript";
String scriptName = "sayHello";
Method scriptMethod = Class.forName(scriptClass).getMethod(scriptName);
scriptMethod.invoke(null, null);
One (quite popular) tool that can help you run Java sources as scripts is JBang. Java programs have to be compiled (to Java class files) to be able to run by a JVM. So, basically, JBang hides this compilation step and invokes the JVM with our compiled class.
In my java code there is class A that has the following line:
Process localProcess = Runtime.getRuntime().exec(myString);
where myString is user supplied input and is passed to exec() at runtime.
Also there is a public method doSomething() in class A.
Can I somehow invoke doSomething() (through reflection, jdwp etc.) using exec() at runtime ?
Starting a new JVM just to call a single method? First, that would be really slow. And second, it would be highly unnecessary!
Reflection is what you want I guess. Here's some sample code.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Class<Main> c = Main.class; // First get the class
try {
Method method = c.getMethod("doSomething"); // get the method by its name
method.invoke(new Main()); // call it on a new instance of Main
} catch (NoSuchMethodException e) {
System.out.println("Method is not found"); // print something when the method is not found
}
}
public void doSomething() {
System.out.println("I have done something!");
}
}
That would mean starting a whole new JVM just to make a method call.
If you are already "within" class A; what prevents you from calling doSomething() directly? Probably: only your lack of skills. If so, then work on your skills; and don't go for the next best solution you heard somebody mention how things might be done!
In essence: a self-claimed geek should always understand each and any concept he is using in his programs. If you want to use reflection, then study what reflection is about.
And please note: letting your users pass in arbitrary strings to have them executed, is a huge security NO GO. You should have mentioned in your question that you want to do this on purpose; and that you are fully aware of the potential consequences of doing so!
EDIT; given your latest comments.
In this case, a solution could be as simple as:
A) you write a new class, like
public class Invoker {
public static void main(String[] args) {
A.doSomething();
or if doSomething isn't static, you will need
A someA = new A( ... however you can create instances of A
A.doSomething()
B) Compile that, and then you can simply send a command like
java -cp WHATEVER Invoker
into your existing application. Of course, you have to work out the details; like providing a valid classpath to that call to java (that classpath has to include the location where Invoker.class lives; and of course A.class; and all of the dependencies that A has).
But keep in mind: doSomething() is executed in the scope of a different JVM. That means that most likely, it will not at all affect class A in that JVM where you trigger the call to exec!
I've got a dll written in Pascal. I've determined that I need to run CoInitialize in the Java code, but I just can't figure out how.
I found another Stack Overflow thread which should have helped here: https://stackoverflow.com/questions/15763993 but I couldn't understand how it actually worked.
My current code that I have now is here:
public interface CSQLLib extends StdCallLibrary {
CSQLLib INSTANCE = (CSQLLib) Native.loadLibrary("DatabaseLibrary", CSQLLib.class);
public HRESULT CoInitialize(Pointer p);
public HRESULT CoUninitialize();
public String doSQLQuery(String input);
public void DllMessage();
}
Example of calling CoInitializeEx from Java code using JNA:
import com.sun.jna.platform.win32.Ole32;
public class Example {
public static void main(String[] args) {
Ole32.INSTANCE.CoInitializeEx(null,Ole32.COINIT_APARTMENTTHREADED);
}
}
Note that use of CoInitializeEx is recommended by both the JNA docs and the Windows SDK docs instead of CoInitialize. CoInitialize(null) is equivalent to CoInitializeEx(null,Ole32.COINIT_APARTMENTTHREADED), but the JNA docs recommend using COINIT_MULTITHREADED instead in Java apps (indeed, they call it "the only sane choice") – however, despite what they say, some COM interfaces only work correctly with COINIT_APARTMENTTHREADED, so it really depends on the COM objects you are using. Whichever you choose, CoInitializeEx is better because it makes it obvious (rather than implicit) which COM threading mode you are using.
Note the solution you mentioned in your comment, calling CoInitialize from within your DLL written in Delphi, is not a good practice. COM should be initialised in the application not in a DLL. If you ever attempt to reuse your DLL in some other application (which is already calling CoInitialize/CoInitializeEx), it is likely your call to it will fail with S_FALSE or RPC_E_CHANGED_MODE because the application will have already initialised it.
I have a native DLL abc.dll (without source code) that was originally used in a JNI call in Java like this:
public class ABC_Proxy
{
private native void callABC(String parameter);
public ABC_Proxy()
{
System.loadLibrary("abc");
}
public void Start(String paramater)
{
callABC(paramater);
}
}
Now I am trying to execute the same function in C#. Using dumpbin I found the correct full entry point, and this is what I came up with so far:
class Abc
{
[DllImport("abc.dll", EntryPoint="_Java_my_namespace_abc_1Proxy_callABC#12")]
private static extern void CallAbc(string parameter);
public void Start(string parameter)
{
CallAbc("test");
}
}
I can see that CallAbc is executed and does something (it creates a file) but then it throws an AccessViolationException, presumably when it tries to access the parameter.
The PureDLLHelper suggests that the function has 3 parameters, and after reading this JNI tutorial I have the feeling that I also need to pass the parameters JNIEnv*, jobject to simulate a JNI call. But from here on I'm lost...
Any idea? Is it even possible what I'm trying to achieve?
Edit: I just want to mention this forum post that has a good explanation of the problems involved and how they could by solved. However, the solutions are based on Xamarin.Android to bridge the C#/Java gap and get hold of the JNIEnv, which is not really an option for me.
Its not going to work, simple as that. The JNI DLL is designed and built to be loaded by the JVM. You will not be able to provide the pointers to the env or jvm that are required to call any of the functions contained in that library. Your only option would be to create a second DLL that creates a new instance of the JVM that then calls the DLL you have, but if you are calling Java from .Net, you may as well keep it all in Java.
I have a library which is written in C++ (actually a Firefox plugin, xyz.dll) and I need to access its methods from Java.
public class AccessLibrary {
public interface Kernel32 extends Library {
public void showVersion();
}
public static void main(String[] args) {
Kernel32 lib = (Kernel32) Native.loadLibrary("xyz.dll", Kernel32.class);
lib.showVersion();
}
}
While executing got the following error:
java -jar dist/accessLibrary.jar
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'showVersion': The specified procedure could not be found.
In the native library source code, the method is defined like this
void CPlugin::showVersion() {
/* ... */
}
I am very new to Java. May be I am missing something basic. Looked into similar questions but none of them solves my problem.
Forgot to mention I am using Windows 7 64bit and Java 7.
First, you cannot export a class method and load it into java. The name will get mangled, and java wouldn't know how to call it properly. What you need to do is break it out into a separate function on its own.
After that:
As already pointed out, make sure you export the function. You can export using one of two ways. The first is what is mentioned, which is to use __declspec( dllexport ). The second is to put it into the def file.
Additionally, make sure you mark it as extern "C" otherwise the name will get mangled. All the details are here: Exporting functions from a DLL with dllexport
So the the signature should be something like this:
extern "C" __declspec(dllexport) void showVersion () {
}
Finally, the depends tool can be downloaded here: http://www.dependencywalker.com/
I think your native library needs to provide a C-style interface, for example
__declspec( dllexport ) void showVersion() {
/* ... */
}
Ideally, take a look at your DLL with depends.exe (which is available through the Windows SDK), there you'll see if your DLL provides the correct function exports.