same problem but with more description....................
source pasted....
Pls help me out.
Fews days back; I completed developement of a JNI module where in I
added support for few C++ native methods to be called from Java. For
those methods native method call succeeds from Java sample program ; it
works till date; But for new methods that I added into module today it
gives me java.lang.UnsatisfiedLinkError.
I used dependency viewer & I tried to find out mangled names; all
functions have something '@X' some number in the end even old methods
too!. After reading so many articles I came to know that it should be
problem with C++ compiler doing some dirty work (name mangling).
somehwhere I got the answer also; advised me to use extern "C" to
prevent that. But to my surprise, .h generated by javah -jni, contains
black extern "C". It means that compiler should not mangle the names;
but doing it! one of the functions that i added earliier "getattrnum"
works fine as explained below.
call to "getattrfloat" gives me unsatisfiedlink error.
I haven't understood 2 things. If this had been a problem of name
mangling by C++ compiler, I would have not able to call any of the
method; but call succeeds for old ones. How come?
Any other way how to prevent "MS" stupid compiler from doing this.
//java file
public class LamiaFunctions{
public void callback(String msg){
System.out.println(msg);
}
public LamiaFunctions(){
}
public native synchronized float getattrfloat(String path,String name);
public native synchronized int getattrnum(String path,String name);
public native synchronized void stop();
static
{
System.loadLibrary("SimulatorJniWrapper");
}
}
//java jni app program
import java.io.*;
import java.math.*;
public class Taz
{
public static void main(String[] main_args)
{
LamiaFunctions fnLamia = new LamiaFunctions();
fnLamia.start();
try
{
Thread.sleep(1000);
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
try
{
if(fnLamia.iscnf() == 1)
{
System.out.println("Already loaded");
}
else
{
fnLamia.loadcnf("3xSAIVL.xml");
}
System.out.println("Configuration File:
"+fnLamia.getcnf());
//below call succeeds : getattrnum
int i = fnLamia.getattrnum("Gas Type");
System.out.println(i);
System.out.println("\n");
//now this call fails getattrfloat, this function newly added into
native
float f = fnLamia.getattrfloat"Max Temp");
System.out.println(f);
System.out.println("\n");
fnLamia.stop();
}
catch(Exception ex)
{
System.out.println("Exception: " + ex);
}
}
}
// cpp functions declarations & definitions in
SimulatorJniWrapper.cpp
JNIEXPORT jint JNICALL Java_LamiaFunctions_getattrnum
(JNIEnv *_jnienv, jobject _jobj, jstring _jpath, jstring _jattr)
{
return 1;
}
JNIEXPORT jfloat JNICALL Java_LamiaFunctions_getattrfloat
(JNIEnv *_jnienv, jobject _jobj, jstring _jpath, jstring _jname)
{
return 1.0
}
I am not able to figure out why call to first method succeeds & fails
on another.
C++ name mangled as follows:
_Java_LamiaFunctions_getattrfloat@16
_Java_LamiaFunctions_getattrnum@16
You happened to mention somewhere in your posting that use compiler
options to prevent c++ name mangling. what are those options for vc++
6.0
Any help on this will really be appriciated.
Regards
Abhijeet
Jean-Francois Briere - 03 Feb 2006 07:22 GMT
This should work on VC++ 6.0.
Go in 'Project Settings', 'C/C++' panel, 'Code Generation' category,
'Calling Convention' combobox:
The setting must be set to : '__cdelc' .
Also be sure that the SimulatorJniWrapper.h file (that you didn't
show) has the following:
-----------------------------------------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jfloat JNICALL Java_LamiaFunctions_getattrfloat
(JNIEnv *_jnienv, jobject _jobj, jstring _jpath, jstring _jname);
JNIEXPORT jint JNICALL Java_LamiaFunctions_getattrnum
(JNIEnv *_jnienv, jobject _jobj, jstring _jpath, jstring _jattr);
#ifdef __cplusplus
}
#endif
-----------------------------------------------------------------------------------------------------------------
Regards
Chris Uppal - 03 Feb 2006 09:48 GMT
> Go in 'Project Settings', 'C/C++' panel, 'Code Generation' category,
> 'Calling Convention' combobox:
> The setting must be set to : '__cdelc' .
Shouldn't make any difference to this issue, since "JNICALL" expands out to
__stdcall.
Of course, changing the option will affect other things...
-- chris
Chris Uppal - 03 Feb 2006 11:46 GMT
> I am not able to figure out why call to first method succeeds & fails
> on another.
[quoted text clipped - 3 lines]
> _Java_LamiaFunctions_getattrfloat@16
> _Java_LamiaFunctions_getattrnum@16
You didn't /read/ my post. Name mangling is not causing your problem.
(Incidentally, I've been checking and it appears that the function lookup code
in the JVM will first look for the properly decorated name
_Java_LamiaFunctions_getattrfloat@16
and, if that fails, will fallback to trying the undecorated version
Java_LamiaFunctions_getattrfloat
That's specific to Windows DLLs of course, but similar logic seems to be used
for other OSes.)
-- chris
Jean-Francois Briere - 03 Feb 2006 20:32 GMT
Just for fun I tried your sample code with JDK 1.5 and VC++ 6.0 and it
works fine.
Regards