获取 jstring/char *?
Get length of jstring/char *?
这是我的 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 中获取长度。
Google 没有任何结果,我缺少什么基本的东西?
由于变量的类型是 const char *
,这表明它是一个 nul
终止的字符串,因此
size_t length = strlen(npath);
应该够了。
尽管您对 bind()
的调用是错误的,但您应该传递地址结构的大小,为此
return bind(sockfd, sun, sizeof(sun));
应该是正确的。
首先,你有内存泄漏。 GetStringUTFChars()
返回的 char*
指针必须 使用 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
值,则需要为每个family
使用不同的sockaddr_...
结构,eg:
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;
}
关于jstring的长度,需要GetStringUTFLength
https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
这应该比在 null 终止的 char* 上调用 strlen 更有效,因为我认为它不需要搜索最终的 null。
这是我的 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 中获取长度。
Google 没有任何结果,我缺少什么基本的东西?
由于变量的类型是 const char *
,这表明它是一个 nul
终止的字符串,因此
size_t length = strlen(npath);
应该够了。
尽管您对 bind()
的调用是错误的,但您应该传递地址结构的大小,为此
return bind(sockfd, sun, sizeof(sun));
应该是正确的。
首先,你有内存泄漏。 GetStringUTFChars()
返回的 char*
指针必须 使用 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
值,则需要为每个family
使用不同的sockaddr_...
结构,eg:
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;
}
关于jstring的长度,需要GetStringUTFLength
https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
这应该比在 null 终止的 char* 上调用 strlen 更有效,因为我认为它不需要搜索最终的 null。