An old win32 project does not compile correctly on new vista 64bit machine.
I do not use 64-bit java.
package org.denkweise.coloredconsole;
public final class Console{
static native void setColor(byte fg, byte bg);
}
goes to ColoredConsole32.h:
#include <jni.h>
JNIEXPORT void __cdecl Java_org_denkweise_coloredconsole_Console_setColor(JNIEnv *, jobject, jbyte, jbyte);
goes to ColoredConsole32.cpp:
#include "ColoredConsole32.h"
#include <windows.h>
JNIEXPORT void __cdecl Java_org_denkweise_coloredconsole_Console_setColor(JNIEnv * env, jobject ob, jbyte fg, jbyte bg) {
/*stuff*/
}
and compile successfully via mingw
g++ -D_JNI_IMPLEMENTATION_ -enable-stdcall-fixup -Wl,--kill-at ColoredConsole32.h -Ic:\jdk1.6.0_26\include -Ic:\jdk1.6.0_26\include\win32 -shared -o ColoredConsole.dll
System.loadLibrary works great, but setColor throws an
java.lang.UnsatisfiedLinkError: org.denkweise.coloredconsole.Console.setColor(BB)V
any sugestions?
OK, was my mistake:
the java-method was static, but the 2nd param of my c-method was jobject instead of jclass.
make the method unstatic solves my problem.
Regards
Related
I am trying to use COFFEE_TRY_JNI on Android, but it does not seem to catch the signal. I just copied the coffeecatch source files in my project, and had to remove some of those parts because Android now apparently has them. I only removed what was "duplicated" (keeping the system one and removing the one in coffeecatch.c).
I get the following crash:
Fatal signal 11 (SIGSEGV), code 2, fault addr 0x7969a63cb6 in tid 20990 (DefaultDispatch)
From this code, calling runNative from Java (well, Kotlin actually):
__attribute__ ((noinline))
static void run() {
char *test = "blah";
*(test + 1) = 'n';
}
__attribute__ ((noinline))
static void run_protected(JNIEnv *env) {
COFFEE_TRY_JNI(env, run());
}
JNIEXPORT void JNICALL
Java_com_example_JniApi_00024Companion_runNative(
JNIEnv *env, jobject thiz) {
run_protected(env);
}
Am I missing something?
I am looking at the MoreTeapots sample:
https://github.com/googlesamples/android-ndk/tree/master/MoreTeapots
and I see that is easy to call a Java method from the C++ code using android_native_app_glue.c by using this method:
jclass clazz = jni->GetObjectClass(app_->activity->clazz);
jmethodID methodID = jni->GetMethodID(clazz, "updateCamera", "(FFF)V");
jni->CallVoidMethod(app_->activity->clazz, methodID, x, y, z);
yet, can I do the reverse in that sample?
Declare a function into java code and that calls the native code. Notice that sample uses "glue"; therefore, the answer is not just these steps:
https://developer.android.com/ndk/samples/sample_hellojni.html
it is different. I see no hooks from java to glue, only from glue to java. I believe glue is running in its own thread.
any leads?
thx!
you could declare a callback in your native code
JNIEXPORT void JNICALL Java_package_Activity_nativeCallback(JNIEnv* jenv, jobject obj);
And then from Java code, just declared as native
native void nativeCallback();
Remember that this execute in main thread, and you should send a command to the background thread to process.
Best regards.
That does not work with "glue". If you look at the sample I mentioned it is different. It uses glue. So I added to the java code:
public native void nativeCallback();
then to native:
extern "C" {
JNIEXPORT void JNICALL Java_com_sample_moreteapots_MoreTeapotsNativeActivity_nativeCallback(JNIEnv *env, jobject obj);
};
JNIEXPORT void JNICALL Java_com_sample_moreteapots_MoreTeapotsNativeActivity_nativeCallback(JNIEnv *env, jobject obj) {
int i = 0;
return;
}
it compiled and linked. But when I tried to invoke the method from Java I get this:
FATAL EXCEPTION: main
Process: com.sample.moreteapots, PID: 31733
java.lang.UnsatisfiedLinkError: No implementation found for void com.sample.moreteapots.MoreTeapotsNativeActivity.nativeCallback()
(tried Java_com_sample_moreteapots_MoreTeapotsNativeActivity_nativeCallback
and Java_com_sample_moreteapots_MoreTeapotsNativeActivity_nativeCallback__)
I'm kinda' new to JNI, but been reading alot about JNI when I wanted to use a legacy dll in my project.
Quick enough, I found out that I can't parameters to native methods. Here's an example that I tried to code with no success:
Hello.java:
package HelloWorld;
Public class Hello {
Private static native int HelloWorld();
Private static native int Mirror(int a);
Static {
System.loadLibrary("Example"); //got path in
vm arguments - works.
}
Public static void main(String[] args) {
Int a = 8;
System.out.println(Mirror(a));
}
Used javah to create header which got me this signature:
JNIEXPORT jint JNICALL Java_HelloWorld_Hello_Mirror (JNIEnv *, jclass, jint);
Wrote a cpp:
Same signature as the h with impl of: "return 1";
That's it and... This is the error I get from eclipse:
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld/Hello.Mirror(I)I
at HelloWorld.Hello.main (Hello.java:14)
These are my ideas:
A. Saw something about c and cpp, am I mixing things.
B. jdk or stuff?
C. The library loads perfectly (checked the other function that does not get parameters), maybe the types are incompatible?
Stuck on this for a while, Hope you guys can help me!
Solved!
Just needed to add '{' around both functions in the cpp file, after the "extern c" command...
I have a working implementation of NDK library and corresponding Java-class. But I am not able to add overloaded method to that class. Currently my class contains:
package com.package;
public class MyClass
{
public static native String getFileName();
static
{
System.loadLibrary("mylib");
}
}
My jniwrappers.cpp file has the following declaration:
JNIEXPORT jstring JNICALL
Java_com_package_MyClass_getFileName(_JNIEnv* env, jobject thiz);
Up to this point everything is working fine. But next I modify my class:
package com.package;
public class MyClass
{
public static native String getFileName();
public static native String getFileName(int index);
...
}
And add to jniwrappers.cpp another declaration:
JNIEXPORT jstring JNICALL
Java_com_package_MyClass_getFileName__I(_JNIEnv* env, jobject thiz, jint index);
It compiles fine, Android application starts, does not get UnsatisfiedLinkError but when it calls the second method with the argument the first C++ function is being called but not the second. I have other methods with arguments in that class but none of them are overloaded so their respective JNI signatures do not contain arguments.
So, what am I doing wrong?
You should use javah tool to generate those signatures.
To use it, build the class file where you have your native function. You'll get a class file.
Run javah -jni com.organisation.class_with_native_func, it'll generate a header file for you.
It's far cleaner than editing it yourself.
You have to add a __ onto the end of the original getFileName function now that it is overloaded. Your 2 C function prototypes should now look like this:
JNIEXPORT jstring JNICALL Java_com_package_MyClass_getFileName__
(JNIEnv *, jclass);
JNIEXPORT jstring JNICALL Java_com_package_MyClass_getFileName__I
(JNIEnv *, jclass, jint);
I am trying to compile the following for the android ndk
#include <jni.h>
#include <string.h>
extern "C" {
JNIEXPORT jstring JNICALL Java_com_knucklegames_helloCpp_testFunction(JNIEnv * env, jobject obj);
};
JNIEXPORT jstring JNICALL Java_com_knucklegames_helloCpp_testFunction(JNIEnv *env, jobject obj) {
return env->NewStringUTF(env, "Hello from native code!");
}
but it is giving the following error
Compile++ thumb: helloCpp <= /cygdrive/c/workspace/helloCpp/jni/main.cpp
/cygdrive/c/workspace/helloCpp/jni/main.cpp: In function '_jstring* Java_com_knucklegames_hello
Cpp_testFunction(JNIEnv*, _jobject*)':
/cygdrive/c/workspace/helloCpp/jni/main.cpp:10: error: no matching function for call to '_JNIEn
v::NewStringUTF(JNIEnv*&, const char [24])'
/cygdrive/d/android/android-ndk-r4b/build/platforms/android-8/arch-arm/usr/include/jni.h:839: note: candidates
are: _jstring* _JNIEnv::NewStringUTF(const char*)
make: *** [/cygdrive/c/workspace/helloCpp/obj/local/armeabi/objs/helloCpp/main.o] Error 1
The NewStringUTF function only takes one argument, a c-string:
env->NewStringUTF("Hello from native code!");
There is a C version that goes like this:
NewStringUTF(env, "Hello from native code!");
But you are obviously using the C++ version.