Second long argument to a JNI call on a Win32 DLL contains zero when it reaches the DLL

P

pcarr01

I have a servlet which makes some JNI calls on a Win32 DLL Like so

Java bits
*******************************
public native RiposteNode getRiposteNode(long GroupId, long
NodeId)throws RiposteException;
......
......

try{
R1 = new RiposteInstance(Frank);
out.println("<br>Frank Riposte is OK");
RiposteNode N = R1.getRiposteNode(123456,32);
out.println("<br>Frank Riposte Marker =
"+N.getMarker());
}catch(RiposteException e)
{
out.println("<br> Exception: Frank
Riposte="+e.toString());
}

It works in that I can pass one argument (123456) to the function and
it will throw exceptions back into the servlet but the second argument
(32) is reported as zero by the DLL, see output at the end.
The DLL relevant DLL code is as follows, it includes some fprintfs for
diagnostic reasons because I am having trouble getting MS VC++ 6.0
(SP5) to do the debug thing.

Any ideas appreciated.

********************************
C++
********************************
include file declaration ( from the javah output )



JNIEXPORT jobject JNICALL
Java_Riposte_RiposteInstance_getRiposteNode
(JNIEnv *, jobject, jlong, jlong);




cpp file

JNIEXPORT jobject JNICALL
Java_Riposte_RiposteInstance_getRiposteNode
(JNIEnv *env, jobject jobj, jlong GroupId, jlong NodeId)
{
FILE* f = fopen("c:\\temp\\getRiposteNode.log","w");
fprintf(f,"%s %d %d \n", "Start of getRiposteNode " ,GroupId ,
NodeId );
fflush(f);

unsigned long RipErrCode;
unsigned char RipErr[1024];
MARKER Mark;
unsigned long dwMarkerDelta;
unsigned long fOnline;
unsigned long fConnected;
// unsigned long dwMarkerGroupId;
unsigned long *pfOnline=&fOnline;
unsigned long *pfConnected=&fConnected;
unsigned long *pdwMarkerDelta=&dwMarkerDelta;
PMARKER pMarker =(unsigned long *) &Mark;
// get node object class
jclass NodeClass = env->FindClass("Riposte/RiposteNode");
fprintf(f,"%s\n", "jclass\n");
fflush(f);
// get method id for ctor using "<init>" in GetMethodID
jmethodID ctor = env->GetMethodID(NodeClass,"<init>","(L,L)V");
fprintf(f,"%s\n", "jclass\n");
fflush(f);
// create new object
jobject Node=env->NewObject(NodeClass, ctor, GroupId,NodeId);
fprintf(f,"%s\n", "jclass\n");
fflush(f);
// make the call & handle the exception
fprintf(f,"%s\n", "before RiposteGetNodeStatus\n");
fflush(f);
if (RipErrCode=RiposteGetNodeStatus(GroupId, NodeId, pfOnline,
pfConnected,
GroupId, pMarker, pdwMarkerDelta))
{
fprintf(f,"%s %d %d \n", "after RiposteGetNodeStatus \n"
,GroupId,NodeId );
fflush(f);
jclass newExcCls;
env->ExceptionDescribe();
env->ExceptionClear();
newExcCls = env->FindClass("Riposte/RiposteException");
if (newExcCls == 0)
{
/* Unable to find the new exception class,
give up.
*/
return Node;
}
if(0!=(RiposteErrorString(RipErrCode,RipErr,1024)))
{
env->ThrowNew(newExcCls, (char*)RipErr);
fprintf(f,"%s\n", "Exception Thrown\n");
fflush(f);
return Node;
}
}
jmethodID sMarker =
env->GetMethodID(NodeClass,"setMarker","([J)V");
fprintf(f,"%s\n", "sMarker\n");
fflush(f);

env->CallVoidMethod(NodeClass,sMarker,Mark);
fprintf(f,"%s\n", "CallVoidMethod\n");
fflush(f);


return Node;
}



************************************
output
************************************
Start of getRiposteNode 123456 0
jclass



jclass



jclass



before RiposteGetNodeStatus



after RiposteGetNodeStatus
123456 0
Exception Thrown
 
G

Gordon Beaton

It works in that I can pass one argument (123456) to the function
and it will throw exceptions back into the servlet but the second
argument (32) is reported as zero by the DLL, see output at the end.

What are sizeof(int) and sizeof(jlong) on your platform? I suspect
that %d is the wrong format specifier for the jlongs you print.

You've got another problem as well, near the end:
jmethodID sMarker = env->GetMethodID(NodeClass,"setMarker","([J)V"); [...]
env->CallVoidMethod(NodeClass,sMarker,Mark);

If setMarker() is a static method, you should be using
GetStaticMethodID() and CallStaticVoidMethod() here.

If it's not, you should be passing Node (not NodeClass) to
CallVoidMethod().

Also, it seems to me that you are doing things in the native method
that would be much easier to do in Java, such as creating the Node.
Why not create it in Java, and pass it to the native method?

Node node = new Node(GroupId, NodeId)
getRiposteNode(GroupId, NodeId, node);

Or, simply call a native method to get the value you want to pass to
setMarker(), and invoke that in Java as well:

Node node = new Node(GroupId, NodeId);
node.setMarker(getRiposteMark(GroupId, NodeId));

Use JNI for the stuff you *can't* do in Java...

/gordon
 
P

pcarr01

Thanks Gordon. I should have spotted that. I have casted the jlongs to
long in my C++ and it now plays OK. A Win32 long is 4 but a jlong is 8.

In respect of the assertion that most code should be in Java I do have
some performance issues to consider but yes, the way you have suggested
I manage Nodes and Markers makes much more sense.

Many thanks for your help.
 
G

Gordon Beaton

Thanks Gordon. I should have spotted that. I have casted the jlongs
to long in my C++ and it now plays OK. A Win32 long is 4 but a jlong
is 8.

In respect of the assertion that most code should be in Java I do
have some performance issues to consider but yes, the way you have
suggested I manage Nodes and Markers makes much more sense.

In that case you should make as *few* calls as possible to JNI
functions (FindClass(), GetMethodID(), CallXXXMethod() and so on) from
your native methods, since they tend to be more expensive than the
Java equivalents.

In general, is is both easier to implement and faster to execute
native code whose input (from Java) comes only from the arguments
passed to it, and whose output goes only through the return value.
Avoid crossing the boundary between Java and native code more than
necessary.

/gordon
 

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

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top