所以我通常在java和Go中编程所以我很抱歉我的无知,我已经学会了基本的c和c ++。但是在玩JNI时,我遇到了这个C代码。
(*env)->ReleaseStringUTFChars(env, javaString, nativeString);
我想知道为什么(* env)指向一个函数。据我所知,env只是一个结构,在C函数中,函数不依赖于类如何在C ++和JAVA中工作的变量。
我是否遗漏了C中的某些内容,只允许函数触发结构?
有点喜欢Go
type House struct { }
func (h House) GetHouseName() string { } //method defined outside of struct, but works on House
不幸的是,我不确定如何说出我在寻找你的东西谷歌并没有真正发现太多,我在C上订购的书籍要到下周才会出现。
感谢您的帮助!
答案 0 :(得分:4)
不,在您的示例中,env
必须是指向结构指针的指针,该指针包含指向函数(!)的指针。
类似的东西:
struct MyEnvironment
{
void (*ReleaseStringUTFChars)(MyEnvironment **env, /*...*/);
};
int main()
{
MyEnvironment *theEnv = AllocEnvironment();
MyEnvironment **env = &theEnv;
(*env)->ReleaseStringUTFChars(env, ...);
}
(稍后会进行一些谷歌搜索......)
碰巧,在JNI中有一点typedef:
typedef const struct JNINativeInterface* JNIEnv;
env
定义为:
JNIEnv *env;
正如我猜测的那样,它实际上是一个指向结构的指针。
C函数的问题在于它们缺少成员函数的概念,因此它们必须在调用函数的对象中包含一个显式参数。
在JNI中,有一个奇怪的预编译器技巧可以使用相同的头和相同的二进制接口使用C和C ++,但语法完全不同。例如,你的C电话:
(*env)->ReleaseStringUTFChars(env, javaString, nativeString);
在C ++中将是:
env->ReleaseStringUTFChars(javaString, nativeString);
这样可行,因为在C ++中env
不是指向指针的指针,而是指向这种类型的指针:
struct JNIEnv
{
const struct JNINativeInterface* functions;
/* inline function: no code generated */
void ReleaseStringUTFChars(jstring string, const char* utf)
{
functions->ReleaseStringUTFChars(this, string, utf);
}
/* a lot of other functions... */
};
由于此类具有指向结构的类型的单个成员,因此它与这样的指针是二进制兼容的,可以在C ++ JNIEnv
和C struct JNINativeInterface *
之间进行转换而没有问题。
答案 1 :(得分:1)
JNIEnv
(env
的类型)是不同的。
如果你看一下JNI的来源,你会看到以下几点:
#ifdef __cplusplus
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv;
#endif
首先看一下C案例,我们看到JNIEnv是一个指向包含一堆函数指针的结构的指针(我这里只包括几个例子):
struct JNINativeInterface_ {
jclass (JNICALL *FindClass)(JNIEnv *env, const char *name);
jfieldID (JNICALL *FromReflectedField)(JNIEnv *env, jobject field);
// ...
}
因此对于C,env
是指向函数指针结构的指针。当您取消引用env
时,您将获得结构,然后取消引用函数指针以调用该函数。这解释了(*env)->ReleaseStringUTFChars(env, javaString, nativeString);
行。
C ++版本使用包含struct JNINativeInterface_
的成员函数的结构:
struct JNIEnv_ {
const struct JNINativeInterface_ *functions;
jclass FindClass(const char *name) {
return functions->FindClass(this, name);
}
}