C++ 访问JVM调用java代码

C++ 访问JVM调用java代码

主程序有C++启动,C++调用java接收字符串,然后c++ 对接收到的字符串进行分词,分词后的结果再返回给java程序。
C++代码
// Defines the entry point for the console application.
//

#include <stdlib.h>
#include <iostream>
#include <jni.h>

#include "Xml4nlp.h"
#include "Ltp.h"

using namespace std;

static XML4NLP xml4nlp;
static LTP ltp(xml4nlp);

string parse(string sentence) {

	ofstream log_file("test.log");
	cout << "Input sentence is: " << sentence << endl;
	xml4nlp.CreateDOMFromString(sentence);
	ltp.crfWordSeg();
	ltp.postag();
	ltp.ner();
	ltp.gparser();
	ltp.srl();
	int wordNum = xml4nlp.CountWordInDocument();
	for (int i = 0; i < wordNum; ++i) {
		const char* word = xml4nlp.GetWord(i);
		if (word != NULL) {
			log_file << word << " ";
		}
	}

	string result;
	xml4nlp.SaveDOM(result);
	cout << "Result is: " << result << endl;
	xml4nlp.ClearDOM();
	return result;
}

jstring str2jstring(JNIEnv* env, const char* pat) {
	//定义java String类 strClass
	jclass strClass = (env)->FindClass("Ljava/lang/String;");
	//获取String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
	jmethodID ctorID = (env)->GetMethodID(strClass, "<init>",
			"([BLjava/lang/String;)V");
	//建立byte数组
	jbyteArray bytes = (env)->NewByteArray(strlen(pat));
	//将char* 转换为byte数组
	(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
	// 设置String, 保存语言类型,用于byte数组转换至String时的参数
	jstring encoding = (env)->NewStringUTF("GB2312");
	//将byte数组转换为java String,并输出
	return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}

std::string jstring2str(JNIEnv* env, jstring jstr) {
	char* rtn = NULL;
	jclass clsstring = env->FindClass("java/lang/String");
	jstring strencode = env->NewStringUTF("GB2312");
	jmethodID mid = env->GetMethodID(clsstring, "getBytes",
			"(Ljava/lang/String;)[B");
	jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
	jsize alen = env->GetArrayLength(barr);
	jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
	if (alen > 0) {
		rtn = (char*) malloc(alen + 1);
		memcpy(rtn, ba, alen);
		rtn[alen] = 0;
	}
	env->ReleaseByteArrayElements(barr, ba, 0);
	std::string stemp(rtn);
	free(rtn);
	return stemp;
}

string receive(jmethodID mid,JNIEnv *env, jclass cls) {
	string ret;

	if (mid != 0) {
		jstring read = (jstring) env->CallStaticObjectMethod(cls, mid);
		//printf("Result of read: %s\n", read);
		string read1 = jstring2str(env, read);
		ret = parse(read1);
	}
	return ret;
}

void send(jmethodID mid,JNIEnv *env, jclass cls,string ret) {

	if (mid != 0) {
		const char* pat=ret.c_str();
		jstring arg = str2jstring(env, pat);
		env->CallStaticObjectMethod(cls, mid, arg);
		//env->ReleaseStringUTFChars(arg, pat);
	}
}

int main(int argc, char *argv[]) {

	cout << "Begin ..." << endl;
	JavaVMOption options[1];
	JNIEnv *env;
	JavaVM *jvm;
	JavaVMInitArgs vm_args;
	long status;
	jclass cls;
	jmethodID mid;
	jint square;
	jboolean not1;
	jstring read;

	options[0].optionString = (char *) "-Djava.class.path=./classes/activemq-all-5.7.0.jar:./classes";
	memset(&vm_args, 0, sizeof(vm_args));
	vm_args.version = JNI_VERSION_1_2;
	vm_args.nOptions = 1;
	vm_args.options = options;
	status = JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);

	if (status != JNI_ERR) {
		cls = env->FindClass("Server");
		if (cls != 0) {
			mid = env->GetStaticMethodID(cls, "await", "()V");
			if (mid != 0) {
				env->CallStaticObjectMethod(cls, mid);
				printf("await ok \n");
			}

			jmethodID rmid = env->GetStaticMethodID(cls, "readReceive",
						"()Ljava/lang/String;");


			jmethodID smid = env->GetStaticMethodID(cls, "putRet",
					"(Ljava/lang/String;)V");

			for (;;) {
				string ret = receive(rmid,env, cls);
				send(smid,env,cls,ret);
			}

		} else {
			printf("cls==0 \n");
		}

		jvm->DestroyJavaVM();
		return 0;
	} else {
		printf("JNI_ERR,%d", status);
		return -1;
	}
}


需要注意的是GetStaticMethodID 第二个参数是方法签名,可以通过jps -s ClassName获取。


Java代码
//package com.datou.analysis.service.cosinecluster;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * User: lixiaoming@qmadou.com
 * Date: 13-4-17
 * Time: 下午2:06
 * To change this template use File | Settings | File Templates.
 */
public class Server {

    static BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10240);
    static AdapterMQMsgSnder snder =  null;
    public static void await() {
        MessageService messageService = new MessageService();
        messageService.setUrl("tcp://localhost:61616");
        messageService.setUser("admin");
        messageService.setPassword("datuu_datuu");

        snder = new AdapterMQMsgSnder();
        snder.setQname("MSG_RES");
        snder.setMessageService(messageService);

        final MQMsgRcver rcver = new MQMsgRcver();
        rcver.setQname("MSG_REQ");
        rcver.setService(messageService);

        Thread tt = new Thread(){
            public void run(){
                for(;;){
                    try {
                        System.out.println("rcvMsgQ begin");
                        String resMsgEntity = rcver.rcvMsgQ();
                        if (resMsgEntity != null) {
                            queue.put(resMsgEntity);
                            System.out.println("get reslt_ok");
                        }
                        System.out.println("rcvMsgQ end");
                    } catch (Exception e) {
                        e.printStackTrace();
                        rcver.closeConnection();
                        Util.sleepSecs(3);
                    }
                }
            }
        } ;
        tt.setDaemon(true);
        tt.start();
    }

    public static String readReceive(){
        String ss = null;
        try {
            ss = queue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ss;
    }

    public static void putRet(String ret){
        System.out.println("putRet ["+ret+"]");
        snder.sendMsgQ(ret);
    }

}



注意 java中使用线程时候,一定要tt.setDaemon(true);否则程序会阻塞。

你可能感兴趣的:(java)