这是我的JNI C代码:
JNIEXPORT jint JNICALL Java_org_avuna_httpd_util_CLibJNI_bind(JNIEnv * this, jclass cls, jint sockfd, jint family, jstring path, jint len) {
struct sockaddr_un sun;
sun.sun_family = family;
const char *npath = (*this)->GetStringUTFChars(this, path, 0);
sun.sun_path = npath;
return bind(sockfd, sun, sizeof(&npath));
}
我猜测(sizeof(&npath)
)如何获得长度是不成功的。我不熟悉C,但我认为有一种方法可以从jstring中获取长度。
谷歌没有产生什么,我错过了什么基本的东西?
答案 0 :(得分:2)
由于变量的类型为const char *
,因此它表明它是nul
终止的字符串,因此
size_t length = strlen(npath);
应该足够了。
虽然,您对bind()
的调用是错误的,但您要传递地址结构的大小,
return bind(sockfd, sun, sizeof(sun));
应该是正确的。
答案 1 :(得分:0)
首先,你有内存泄漏。 char*
返回的GetStringUTFChars()
指针必须使用ReleaseStringUTFChars()
释放,您没有这样做。
其次,bind()
要求您指定sockaddr_un
结构的字节大小,而不是npath
的字符长度。此外,bind()
的第二个参数需要sockaddr*
指针作为输入。
第三,sockaddr_un::sun_path
是char[]
数组,您无法为其指定char*
指针。您必须复制指向的内容。
试试这个:
JNIEXPORT jint JNICALL Java_org_avuna_httpd_util_CLibJNI_bind(JNIEnv * this, jclass cls, jint sockfd, jint family, jstring path, jint len)
{
struct sockaddr_un sun;
memset(&sun, 0, sizeof(sun));
sun.sun_family = family;
const char *npath = (*this)->GetStringUTFChars(this, path, 0);
strncpy(sun.sun_path, npath, UNIX_PATH_MAX);
(*this)->ReleaseStringUTFChars(this, path, npath);
return bind(sockfd, (struct sockaddr *) &sun, sizeof(sun));
}
话虽如此,sockaddr_un
始终使用AF_UNIX
作为其系列,因此将family
作为输入值传递是没有意义的。如果您需要传递不同的family
值,则需要为每个sockaddr_...
使用不同的family
结构,例如:
JNIEXPORT jint JNICALL Java_org_avuna_httpd_util_CLibJNI_bind(JNIEnv * this, jclass cls, jint sockfd, jint family, jstring path, jint len)
{
switch (family)
{
case AF_UNIX:
{
struct sockaddr_un sun;
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
const char *npath = (*this)->GetStringUTFChars(this, path, 0);
strncpy(sun.sun_path, npath, UNIX_PATH_MAX);
(*this)->ReleaseStringUTFChars(this, path, npath);
return bind(sockfd, (struct sockaddr *) &sun, sizeof(sun));
}
case AF_INET:
{
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
const char *npath = (*this)->GetStringUTFChars(this, path, 0);
inet_pton(AF_INET, npath, &sin.sin_addr);
sin.sin_port = 0;
(*this)->ReleaseStringUTFChars(this, path, npath);
return bind(sockfd, (struct sockaddr *) &sin, sizeof(sin));
}
case AF_INET6:
{
struct sockaddr_in6 sin;
memset(&sin, 0, sizeof(sin));
sin.sin6_family = AF_INET6;
const char *npath = (*this)->GetStringUTFChars(this, path, 0);
inet_pton(AF_INET6, npath, &sin.sin6_addr);
sin.sin6_port = 0;
(*this)->ReleaseStringUTFChars(this, path, npath);
return bind(sockfd, (struct sockaddr *) &sin, sizeof(sin));
}
// and so on ...
}
return -1;
}
答案 2 :(得分:0)
关于jstring的长度,需要的是GetStringUTFLength。
https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
这应该比对以null结尾的char *调用strlen更为有效,因为我认为它不需要搜索最终的null。