C++调用JAVA是JAVA的反射原理。
package ;
import .*;
public class test {
private JFrame mframe;
private JButton btn;
private JPanel panel;
private JLabel label;
public test() {
mframe = new JFrame();
("Hello");
(300, 300);
panel = new JPanel();
(100, 100);
btn = new JButton("按钮");
(100, 100);
(btn);
label = new JLabel("hello");
(label);
().add(panel);
(true);
(JFrame.EXIT_ON_CLOSE);
}
static {
("jnitest");
}
public native String testfuc(String instring);
void Settxt(String txt)
{
(txt);
}
public static void main(String[] srgs)
{
test testx = new test();
("hello");
}
}
#include <>
void log(char* TAG)
{
char buf[256] = { 0 };
sprintf(buf, "%s:thread id %d", TAG,::GetCurrentThreadId());
OutputDebugStringA(buf);
}
JavaVM* javavm;
JNIEnv * envm;
jobject obj;
int x = 0;
char buf[25];
DWORD __stdcall th2(void* lp)
{
log("th2 begin");
JNIEnv* env;
javavm->AttachCurrentThread((void**)(&env), NULL);
log("th2 end");
while (true)
{
sprintf(buf, "%d", x * 10);
jstring rtstr2 = env->NewStringUTF(buf);
env->GetObjectClass(obj);
jclass cl = env->GetObjectClass(obj);
jmethodID id = env->GetMethodID(cl, "Settxt", "(Ljava/lang/String;)V");
env->CallVoidMethod(obj, id, rtstr2);
x++;
Sleep(1000);
}
return 0;
}
DWORD __stdcall th(void* lp)
{
::CreateThread(NULL, 0, LPTHREAD_START_ROUTINE(th2), NULL, 0, 0);
log("th1 begin");
JNIEnv* env;
javavm->AttachCurrentThread((void**)(&env), NULL);
log("th1 end");
while (true)
{
sprintf(buf, "%d", x * 10);
jstring rtstr2 = env->NewStringUTF(buf);
env->GetObjectClass(obj);
jclass cl = env->GetObjectClass(obj);
jmethodID id = env->GetMethodID(cl, "Settxt", "(Ljava/lang/String;)V");
env->CallVoidMethod(obj, id, rtstr2);
x++;
Sleep(1000);
}
return 0;
}
static jstring JNICALL Test(JNIEnv *env, jobject arg, jstring instring)
{
envm = env;
const char *str = (const char *)env->GetStringUTFChars(instring, JNI_FALSE);
env->ReleaseStringUTFChars(instring, str);
x++;
sprintf(buf, "%d", x);
jstring rtstr = env->NewStringUTF(buf);
sprintf(buf, "%d", x*10);
jstring rtstr2 = env->NewStringUTF(buf);
jclass cl = env->GetObjectClass(arg);
jmethodID id= env->GetMethodID(cl, "Settxt", "(Ljava/lang/String;)V");
env->CallVoidMethod(arg, id, rtstr2);
obj= env->NewGlobalRef(arg);
::CreateThread(NULL, 0, LPTHREAD_START_ROUTINE(th), NULL, 0, 0);
return rtstr;
}
static const JNINativeMethod gMethods[] = {
{ "testfuc", "(Ljava/lang/String;)Ljava/lang/String;", (void*)Test }
};
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void *reserved)
{
javavm = vm;
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv( (void**)&env, JNI_VERSION_1_4) != JNI_OK)
return -1;
jclass clazz;
static const char* const kClassName = "com/ui/test/test";
clazz =env->FindClass(kClassName);
if (clazz == NULL)
{
::MessageBoxA(0, "JNI_OnLoad", kClassName, 0);
return -1;
}
if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
{
printf("register native method failed!\n");
return -1;
}
return JNI_VERSION_1_4;
}
- JNI_OnLoad 保存JavaVM指针
- 在JAVA调用在JAVA调用C++时,保存JAVA对象,obj= env->NewGlobalRef(arg)使得对象可以全局共享
- 多线程中使用javavm->AttachCurrentThread 附加线程到Java线程中
- 附加线程后,使用env->GetObjectClass(obj) 获取对象的class
- AttachCurrentThread 不会立刻修改线程id,不知什么原理