1827849 Members
1691 Online
109969 Solutions
New Discussion

Re: calling C from java

 
SAMI AHMAD
Regular Advisor

calling C from java

I am seeing few examples here on how to call Cobol or Fortran from java but I couldnt find any document or example on how to call C from java ..can someone point me in the right direction?

thanks
29 REPLIES 29
Mike Kier
Valued Contributor

Re: calling C from java

Tim Sneddon from Kednos had a good article, "Calling OpenVMS native routines from Java," in the OpenVMS Technical Journal, Volume 12 (http://h71000.www7.hp.com/openvms/journal/index.html) which, although using a PLI example, should (and claims to be) extensible to C.
Practice Random Acts of VMS Marketing
Duncan Morris
Honored Contributor

Re: calling C from java

John Gillings
Honored Contributor

Re: calling C from java

SAMI,

Calling C shouldn't be any different from Cobol or Fortran. The VMS calling standard is specifically designed to make intra language calls possible, and relatively painless.

The biggest issue is matching data types between the languages. There should be a better match for data types between Java and C, as you may not need to worry about string descriptors and packed decimal types.

Start with your existing Fortran example, and replace the Fortran routine with a C equivalent. Make sure you can receive and return all the data types you're interested in.

I'd expect far more people to be calling C from Java than Cobol. Chances are, the reason you can't find any example code is it's too easy!
A crucible of informative mistakes
Guy Peleg
Respected Contributor

Re: calling C from java

Sami,

Please contact me offline and I would
be happy to provide you with few examples
that call C from Java.

Regards,

Guy Peleg
Maklee Engineering
www.maklee.com
guy.peleg@company_name.com
SAMI AHMAD
Regular Advisor

Re: calling C from java

whats your email address?
Hoff
Honored Contributor

Re: calling C from java

What is Guy's address? Since you're looking for help with the JNI and that's going to put you rather deep into the Java and C coding requirements, here is the answer to your question in the form of some C coding practice.

:-)

$ type y.c
#include
main() { printf("guy.peleg@%s.com","maklee"); return 1; }
$
$ cc y
$ link y
$ run y
[the answer appears here]
$

SAMI AHMAD
Regular Advisor

Re: calling C from java

iam willing to take the challange :)
thanks
Jean-François Piéronne
Trusted Contributor

Re: calling C from java

Sami,

you can also use SWIG, which generates the jackets routines: http://www.swig.org/

SWIG 1.3.31 has been ported on OpenVMS and I have extensively used it without any problem (but not with java...)

JF
SAMI AHMAD
Regular Advisor

Re: calling C from java

based on Guy Peleg's example I am trying to put together this extern C program call, can someone point out why iam unable to compile ?
Guy thanks for your valuable example to give me a starting point.


SUNNY2$ type snd_snmp.java
class SYSTEMCALL {
public native int SNMPTRAP (String msg);
static {
System.loadLibrary("SNDSNMP_C");
}
public static void main (String[] args) {

System.out.println("This is java ..calling the C routing");
int result = new SYSTEMCALL().SNMPTRAP("TEST TRAP MSG");
System.out.println("for now lets omit this");
}
}



$ javac snd_snmp.java

$ javah -jni "SYSTEMCALL"

$TYPE SYSTEMCALL.H

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class SYSTEMCALL */

#ifndef _Included_SYSTEMCALL
#define _Included_SYSTEMCALL
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: SYSTEMCALL
* Method: SNMPTRAP
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_SYSTEMCALL_SNMPTRAP
(JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif



SUNNY2$ type sndsnmp_c.c
#include "SYSTEMCALL.H"
#include
#include
#include

#define size 512
static char cmdbuffer[size];

/* main(int argc, char **argv ) */

JNIEXPORT jint JNICALL Java_SYSTEMCALL_SNMPTRAP
(JNIEnv *env, jobject obj , jstring cmdbuffer) {

int i;
int sts;
char *cmd = "mcr sys$system:tcpip$snmp_trapsnd.exe 0.0 local 0 0 0 -h 10.100.18.245 -v2c 1.3.6.1.6.3.1.1.4.1.0 \"D\"";

strncat (cmdbuffer, cmd,size);
strncat (cmdbuffer, " \"",size);
strncat (cmdbuffer, argv[1],size);
strncat (cmdbuffer,"\"",size);
printf ("%s\n",cmdbuffer);
sts = system(cmdbuffer);
printf( " sts = %%x%08x.\n", sts);
}
SUNNY2$

SUNNY2$ cc /prefix=all/float=ieee/ieee=denorm/defin=JIT_OPTION/names=(short,as_is)
/reent=multithread/includ=SYS$COMMON:[JAVA$142.INCLUDE...] SNDSNMP_C

SUNNY2$ cc /prefix=all/float=ieee/ieee=denorm/defin=JIT_OPTION/names=(short,as_is) /reent=multithread/includ=SYS$COMMON:[JAVA$142.
INCLUDE...] SNDSNMP_C

strncat (cmdbuffer, cmd,size);
.............^
%CC-W-PTRMISMATCH, In this statement, the referenced type of the pointer value "cmdbuffer" is "struct _jobject", which is not compat
ible with "char".
at line number 18 in file DISK$ORACLE:[ORACLE9I]SNDSNMP_C.C;18


Dennis Handly
Acclaimed Contributor

Re: calling C from java

>can someone point out why I am unable to compile?

You have:
static char cmdbuffer[size];
JNIEXPORT jint JNICALL Java_SYSTEMCALL_SNMPTRAP
(JNIEnv *env, jobject obj, jstring cmdbuffer) {

Your parm name cmdbuffer hides your file scope definition.

If you were using a real language like C++, you could just use ::cmdbuffer to access the global scope. :-)
Martin Vorlaender
Honored Contributor

Re: calling C from java

Apart from cmdbuffer used twice, jstring is NOT an ordinary C char*. You'll have to convert the jstring parameter - see http://java.sun.com/docs/books/jni/html/objtypes.html#4001 , especially the methods GetStringChars and GetStringLength.

cu,
Martin
x2084
Trusted Contributor

Re: calling C from java

After learning C or a "real" languages and how to call their functions from Java in order to do a system() with a C-style string retrieved from a Java and/or C++ string class, you may want to learn what the Runtime class can do for you.
SAMI AHMAD
Regular Advisor

Re: calling C from java

ok I am not getting compiler errors now after i made the following change but iam now not able to run it using java

static char cmdbuffer[size];

/* main(int argc, char **argv ) */

JNIEXPORT jint JNICALL Java_SYSTEMCALL_SNMPTRAP
(JNIEnv *env, jobject obj , jstring msg) {

int i;
int sts;
char *cmd = "mcr sys$system:tcpip$snmp_trapsnd.exe 0.0 local 0 0 0 -h 10.100.18.245 -v2c 1.3.6.1.6.3.1.1.4.1.0 \"D\"";

char buf[512];
const jbyte *str;
str = (*env)->GetStringUTFChars(env, msg, NULL);
if (str == NULL) {
return NULL; /* OutOfMemoryError already thrown */
}
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, msg, str);


/* strncat (cmdbuffer, cmd,size);
strncat (cmdbuffer, " \"",size);
strncat (cmdbuffer, argv[1],size);
strncat (cmdbuffer,"\"",size);
printf ("%s\n",cmdbuffer);
sts = system(cmdbuffer);
printf( " sts = %%x%08x.\n", sts);
*/
return 0;
}

$link/share=sndsnmp_c sndsnmp_c,sndsnmp_c/opt

$ JAVA "SYSTEMCALL" "testing"
Warning: JIT compiler "SUNCOMPILER" not found. Will use interpreter.
Exception in thread "main" java.lang.UnsatisfiedLinkError: no SNDSNMP_C in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1578)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:834)
SAMI AHMAD
Regular Advisor

Re: calling C from java

and my options file looks like this :

SUNNY2$ type sndsnmp_c.opt
case_sensitive=YES
symbol_vector=(Java_SYSTEMCALL_SNMPTRAP=PROCEDURE)
case_sensitive=NO
java$java_shr/share
gsmatch=lequal,1,1
SAMI AHMAD
Regular Advisor

Re: calling C from java

looking at the files in sys$common:[java$142.vms_demo...]build_example.com , I see following which is confusing me, what
is the function of the libgesyi logical pointing to the shared image ? I didnt define any such logical, is this the reason iam getting error? how is this logical name constructed ?

$ link/share=getjpi_shr.exe getjpi_nat.obj,getjpi.opt/opt,java.opt/opt
$ link/debug/share=getjpi_g_shr.exe getjpi_nat.obj,getjpi.opt/opt,java_g.opt/opt
$
$ define/nolog libgetsyi sys$disk:[]getsyi_shr.exe
$ define/nolog libgetsyi_g sys$disk:[]getsyi_g_shr.exe
$

SAMI AHMAD
Regular Advisor

Re: calling C from java

ok I found on HP site how to link the image properly and that fixed the issue so now i can concentrate on application errors , any ideas why iam getting those special characters instead of the string that iam inputting as parameter?


SUNNY2$ link/share/exec=java$sndsnmp_c_shr.exe sndsnmp_c,sndsnmp_c/opt

SUNNY2$ def/job/log java$sndsnmp_c_shr sys$login:java$sndsnmp_c_shr.exe
SUNNY2$ JAVA "SYSTEMCALL" "TESTING"
Warning: JIT compiler "SUNCOMPILER" not found. Will use interpreter.
This is java ..calling the C routing
@²UP²Uà`UU0lŸz;lŸz6for now lets omit this


Martin Vorlaender
Honored Contributor

Re: calling C from java

>>>
any ideas why iam getting those special characters instead of the string that iam inputting as parameter?
<<<

Because you're not using it?

- The jstring parameter msg is probably not UTF8 encoded. That's why I suggested GetStringChars and not GetStringUTFChars.
- The jbyte variable str is not a null-terminated C string. That's why I suggested using GetStringLength

cu,
Martin
Hoff
Honored Contributor

Re: calling C from java

There are Java SNMP libraries widely available that can send SNMP traps, and various of which would seem more supportable than this current approach.
SAMI AHMAD
Regular Advisor

Re: calling C from java

sorry i think the code is not upto date . iam using jstring n not jbyte

jstring jstr;
jstr = (*env)->NewStringUTF(env, result);
if (jstr == NULL) {
fprintf(stderr, "out of memory");
return 0;
}

printf("%s","now in C routine");
printf("%s", jstr);
SAMI AHMAD
Regular Advisor

Re: calling C from java

Hi Hoff !

i wouldnt love to make the current method work as this would open ways of interfacing.
but can you point me to a sample code using such snmp trap java calls?

thanks
Hoff
Honored Contributor

Re: calling C from java

Well, I looked around for this stuff using the following query:

http://www.google.com/search?q=java+send+snmp+trap

I'm sure this could be further refined.

SAMI AHMAD
Regular Advisor

Re: calling C from java

tHANKS Hoff I will look into it. First let me get this JNI working :)
SAMI AHMAD
Regular Advisor

Re: calling C from java

Martin !
I changed the code to use Getstringchars but I am still getting the same problem, string is not being translated..

SUNNY2$ TYPE sndsnmp_c.c;
#include "SYSTEMCALL.H"
#include
#include
#include

#define size 512
static char cmdbuffer[size];

/* main(int argc, char **argv ) */

JNIEXPORT jint JNICALL Java_SYSTEMCALL_SNMPTRAP
(JNIEnv *env, jobject obj , jstring msg) {

int i;
int sts;
char *cmd = "mcr sys$system:tcpip$snmp_trapsnd.exe 0.0 local 0 0 0 -h 10.100.18.245 -v2c 1.3.6.1.6.3.1.1.4.1.0 \"D\"";

jboolean *iscopy;
jstring ret;
jint len;
const jchar *fmt;
fmt = (*env)->GetStringChars(env, msg, iscopy);
len = (*env)->GetStringLength(env, msg);
ret = (*env)->NewString(env, fmt,len);

printf("%s","now in C routine");
printf("%s", ret);

return 0;
}

SUNNY2$ java "SYSTEMCALL"
Warning: JIT compiler "SUNCOMPILER" not found. Will use interpreter.
This is java ..calling the C routing
now in C routineh²Ux²Uà`UU0lŸz;lŸz6
SAMI AHMAD
Regular Advisor

Re: calling C from java

ok Iam very close to fixing this code. I am getting the correct length of the string but Iam only seeing the first character of the string , how can I capture the whole ?

jboolean *iscopy=0;
jstring ret;
jint len;
const jchar *fmt; << it wont lt me use
jstring here .
fmt = (*env)->GetStringChars(env, msg, iscopy);
len = (*env)->GetStringLength(env, msg);

printf("%d\n", len);
printf("%s\n","now in C routine");
printf("%s", fmt);



SUNNY2$ java "SYSTEMCALL"
Warning: JIT compiler "SUNCOMPILER" not found. Will use interpreter.
This is java ..calling the C routing
18 <<<<< correct string length
now in C routine
N <<<<< only the first char of msg string
which is 'NEW TEST TRAP MSGS'