Hi Dave,
You need to use the Java Invocation API, which is part of JNI, to
create a Java VM. Then you get a class ID for the class you
want loaded, a method ID for the method you need to invoke,
and call the appropriate JNI call to invoke the method.
I've attached some sample code that does this; this is part of
the never-quite-released VPLUS Class Library for Java. I've
snipped it heavily since much of the code is duplicated over
and over again for each intrinsic; I've left in the part dealing
with the invocation API and just enough of the rest to let
you follow what's going on (I think).
There's quite a bit more example JNI code available on Jazz
in one of the first tutorials I wrote. The MPE Class Library
for Java and the TurboIMAGE Class Library for Java, both of
which are downloadable from www.interex.org under the shared
source program, use JNI extensively and can be used as
examples.
Mike
Dave ([log in to unmask]) wrote:
: Hi.
: I'm trying to call some java code from one of our legacy COBOL applications.
: I
: understand that the way to do this is to set up a C stub using the JNI to
: call
: the java, and then to call the C from the COBOL, but I really have no idea
: where to start.
: Does anyone know where I can find an example of this, or does anyone have
: some
: sample code they can let me have?
: Any help would be greatly appreciated. I think my head is about to explode.
: Dave.
: ------------------------------------------------------------
: Get your FREE web-based e-mail and newsgroup access at:
: http://MailAndNews.com
: Create a new mailbox, or access your existing IMAP4 or
: POP3 mailbox from anywhere with just a web browser.
: ------------------------------------------------------------
--
-----------------------------------------------------------------
Mike Yawn
Hewlett-Packard email [log in to unmask]
Commercial Systems Division Phone (916) 748-3865
8000 Foothills Blvd MS 5219
Roseville, CA 95747
-----------------------------------------------------------------
/* vpluscalls.c
*
* What this is:
* This code will go into an XL that will be placed along an
* application's linkage path, intercepting any calls to
* VPLUS intrinsics. When the first call (VOPENTERM or VOPENFORMF)
* is intercepted, a slaved VM will be created using the
* invocation interface (desired enhancement: option to connect to
* an existing VM and get a private execution thread).
* Each VPLUS call will cause a corresponding Java method in
* class com/hp/vplus/VPlusCalls to be called with the same arguments.
*/
#include <jni.h>
#include "comarea.h"
/* Standard invocation API */
static JNIEnv *env;
static JavaVM *jvm;
static int initialized=0;
/* MPE Extensions to invocation API */
int MPEStackHWM;
int MPEStackLimit;
extern int JavaStackAvail(int);
/* Class, Method, and Field IDs */
static jclass classString;
static jclass classVPlus;
static jmethodID methodVChangeField;
static jmethodID methodVCloseFormF; /* XL does part */
static jmethodID methodVCloseTerm;
static jmethodID methodVErrMsg;
static jmethodID methodVFieldEdits;
static jmethodID methodVFinishForm;
/* lots more method ids were here, snipped */
static jclass classComArea;
static jmethodID methodComAreaInit;
static jmethodID methodGetBufferStatus;
static jmethodID methodGetCFName;
static jmethodID methodGetCMode;
/* lots more method ids were here, snipped */
static jclass classFieldSpec;
static jmethodID methodFieldSpecInit;
void initIDs(); // forward declaration
#define UPDATE_SHORT(fieldname) \
((comarea_type *)comarea)->fieldname = \
(*env)->CallShortMethod(env, jcomarea, methodGet##fieldname)
#define UPDATE_INT(fieldname) \
((comarea_type *)comarea)->fieldname = \
(*env)->CallIntMethod(env, jcomarea, methodGet##fieldname)
#define UPDATE_STRING(fieldname) \
{ \
jboolean isCopy; \
char *contents; \
jstring jdata = (jstring) \
(*env)->CallObjectMethod(env, jcomarea, methodGet##fieldname);\
contents = (*env)->GetStringUTFChars(env, jdata, &isCopy); \
strcpy(contents,((comarea_type *)comarea)->fieldname); \
}
/* !! This is the key part !! */
void initialize_vm()
{
JDK1_1InitArgs vm_args;
int ret, len;
char *newcp;
if (!MPENMStackOK() ) {
exit(2);
}
vm_args.version = 0x00010001;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
// Adjust classpath. This hard-coded path is temporary.
#define MY_CLASSPATH "/YAWN/CLASSLIB/:.:"
len = strlen(MY_CLASSPATH) + strlen(vm_args.classpath) + 1;
newcp = (char *)malloc(len);
strcpy(newcp, MY_CLASSPATH);
strcat(newcp, vm_args.classpath);
vm_args.classpath = newcp;
ret = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
if (ret < 0) {
fprintf(stderr, "Can't create JVM. Error: %d\n", ret);
exit(2);
}
initIDs();
initialized = 1;
}
void initIDs()
{
jclass localRef;
// Initialize Class IDs
localRef = (*env)->FindClass(env, "com/hp/vplus/ComArea");
if (localRef == 0) printf("Bad CID: ComArea\n");
classComArea = (*env)->NewGlobalRef(env, localRef);
/* more class ids snipped */
// Initialize Method IDs
// ComArea
methodComAreaInit = (*env)->GetMethodID(env, classComArea,
"<init>", "([B)V");
if (methodComAreaInit == 0) printf("Bad MID: ComArea<init>\n");
methodGetCFName = (*env)->GetMethodID(env, classComArea,
"getCFName", "()Ljava/lang/String;");
if (methodGetCFName == 0) printf("Bad MID: getCFName\n");
/* lots more method ids snipped */
}
terminate_vm()
{
(*jvm)->DestroyJavaVM(jvm);
initialized = 0;
}
jobject make_jcomarea(char *comarea)
{
jobject jcomarea;
jbyteArray jcomdata;
jsize jcomlen = ((comarea_type *)comarea)->ComAreaLen;
if (!initialized) initialize_vm();
jcomdata = (*env)->NewByteArray(env, jcomlen);
(*env)->SetByteArrayRegion(env, jcomdata, 0, jcomlen, comarea);
jcomarea = (*env)->NewObject(env, classComArea, methodComAreaInit,
jcomdata);
return jcomarea;
}
/* will just show one intrinsic as an example */
void vchangefield(char *comarea, char *specbuffer, short numentries)
{
jobject jcomarea = make_jcomarea(comarea);
jobject jspecbuf;
jbyteArray jspecdata;
jsize jbuflen = numentries * 8; /* 8 bytes per entry */
jspecdata = (*env)->NewByteArray(env, jbuflen);
(*env)->SetByteArrayRegion(env, jspecdata, 0, jbuflen,
specbuffer);
jspecbuf = (*env)->NewObject(env, classFieldSpec, methodFieldSpecInit,
jspecdata);
(*env)->CallStaticVoidMethod(env, classVPlus, methodVChangeField,
jcomarea, jspecbuf, (jshort) numentries);
UPDATE_SHORT(CStatus);
}
|