So I created a JNI-C++ dll for Microsoft Sapi 5.4. The program executes smoothly.
But even if I call the System.exit(int)
in the main of the java program, the program still remain running. I'm using netbeans for the java coding. Additionally, the Runtime.getRuntime().addShutdownHook()
is never called.
Any pointer why this keeps happening.
UPDATE: the problem is not with the shutdownhook. The problem occurred whenever a pointer is being delete
. Whenever the deleteTTS and the destructor call the delete
function, the native side just keeps hanging up.
Code snippet:
JavaVM * javaVM;
jobject javaObj;
//different java callback variables
long speechObjId;
std::wstring theString(L"");
bool debug;
CRESpeechLib::CRESpeechLib(){
init(1);
}
CRESpeechLib::CRESpeechLib(int val){
init(val);
}
CRESpeechLib::~CRESpeechLib(){
this->isInit = false;
print("Calling destructor of " + this->id);
this->ttsInterface.unload();
this->ttsInterface.getVoicePt()->SetNotifySink(NULL);
}
void CRESpeechLib::init(int val){
this->isInit = true;
this->id = val;
print("Creating Class: " + this->id);
this->ttsInterface.load();
}
bool CRESpeechLib::say(const std::string &sentence){
bool balik = this->ttsInterface.say(sentence);
return balik;
}
void CRESpeechLib::removeNotify(){
this->ttsInterface.getVoicePt()->SetNotifySink(NULL);
}
ISpVoice* CRESpeechLib::getVoicePointer(){
return this->ttsInterface.getVoicePt();
}
JNIEXPORT jboolean JNICALL Java_com_example_MainClass_speak(JNIEnv *env, jobject obj, jlong ptID, jstring str){
const char *nativeString = env->GetStringUTFChars(str, FALSE);
std::string temp(nativeString);
theString = std::wstring(temp.begin(), temp.end());
jboolean ret;
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
ret = pt->say(nativeString);
env->ReleaseStringUTFChars(str, nativeString);
return ret;
}
JNIEXPORT jobjectArray JNICALL Java_com_example_MainClass_getVoices(JNIEnv *env, jobject thisObj, jlong ptID){
jobjectArray ret;
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
std::vector<std::string> list = pt->getVoices();
ret = (jobjectArray) env->NewObjectArray(list.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
int i = 0;
for (std::vector<std::string>::iterator it = list.begin(); it != list.end(); ++it) {
env->SetObjectArrayElement(ret, i, env->NewStringUTF((*it).c_str()));
i++;
}
return(ret);
}
JNIEXPORT void JNICALL Java_com_example_MainClass_removeNotify(JNIEnv *env, jobject obj, jlong ptID){
//jboolean ret;
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
pt->removeNotify();
return;
}
JNIEXPORT jlong JNICALL Java_com_example_MainClass_createTTS(JNIEnv *env, jobject obj, jint id){
//init variables for the JNI callback
CRESpeechLib *pt = new CRESpeechLib(id);
return (jlong) pt;
}
JNIEXPORT void JNICALL Java_com_example_MainClass_deleteTTS(JNIEnv *env, jobject obj, jlong ptID){
print("Delete called");
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
pt->removeNotify();
delete pt;
delete javaVM;
env->DeleteGlobalRef(javaObj);
return;
}
void __stdcall outsideeventFunction(WPARAM wParam, LPARAM lParam){
//event handling of tts
return;
}
void wordBoundaryCallback(int start, int end) {
//call java method wordBoundaryCallback
}
HRESULT WaitAndPumpMessagesWithTimeout(HANDLE hWaitHandle, DWORD dwMilliseconds)
{
//create the pump message
return hr;
}
////////////////////////////JAVA CODES///////////////////////////////////
//Assume all native codes are already declared
public MainClass(){
this.id = 1;
addressRef = createTTS(id);
System.out.println("Class reference: " + addressRef);
this.attachShutDownHook();
}
public MainClass(int id){
this.id = id;
addressRef = createTTS(id);
System.out.println("Class reference: " + addressRef);
this.attachShutDownHook();
}
public void wordBoundaryReach(int start, int end){
System.out.println("From CB: Start: " + start + "\t\tEnd: " + end);
}
public boolean speak(String msg){
return speak(addressRef, msg);
}
public boolean setVoice(String name){
return setVoice(addressRef, name);
}
public void deleteTTS(){
deleteTTS(addressRef);
}
private void attachShutDownHook(){
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
MainClass.this.deleteTTS(addressRef);
System.out.println("Inside Add Shutdown Hook");
}
});
System.out.println("Shut Down Hook Attached.");
}
public static void main(String[] args) {
MainClass t = new MainClass(1);
String[] s = (String[])t.getVoices();
t.setVoice(s[0]);
if(t.speak("Testing the functionalities from the library. I hope this is fine. Let us try another sentence for the sake of a long speech.")){
System.out.println("Tapos na. Success");
}else{
System.out.println("Tapos na. Failed");
}
System.exit(0);
}