JNI problem: How to prevent VC++ compiler from doing name mangling

A

abhijeet.s

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!

I haven't understand 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.

Any help on this will really be appriciated.

Regards
Abhijeet
 
A

Alan Krueger

abhijeet.s said:
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).

Actually, the C++ compiler does much worse than add @NNN at the end of
method names. See the following for details on the @NNN:

http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_Microsoft_Windows
 
A

abhijeet.s

Could you do it for me on this:

JNIEXPORT jfloat JNICALL Java_Functions_getattrfloat (JNIEnv *,
jobject, jstring, jstring);

Regards
Abhijeet
 
C

Chris Uppal

abhijeet.s said:
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!

Not quite. Even 'C' compilation/linkage can do /some/ name mangling. Exactly
what depends on whether you are using the "__stdcall" or "__cdecl" calling
convention, I believe (but I'm not sure of the details).

As far as I can see from checking a small JNI DLL that I had lying around, the
"correct" compilation options (which were just the defaults) plus the stuff
generated by javah, results in a DLL with names decorated as you describe. So
I think your compilation is probably OK, but that something else is going wrong
somewhere (finding an old copy of the DLL(s) perhaps ?).

It is possible to control what names appear in the DLL by using a .def file,
but I don't believe that would work here (although its a very good idea for
general-purpose DLLs) since the JVM will work out what names to look for and it
will be looking for names with the @X decoration.

-- chris
 
A

abhijeet.s

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
 
J

Jean-Francois Briere

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
 
C

Chris Uppal

Jean-Francois Briere said:
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
 
C

Chris Uppal

abhijeet.s said:
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 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
 
J

Jean-Francois Briere

Just for fun I tried your sample code with JDK 1.5 and VC++ 6.0 and it
works fine.

Regards
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top