简体   繁体   English

获取jstring / char的长度*?

[英]Get length of jstring/char *?

This is my JNI C code: 这是我的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));
}

I just guessed unsuccessfully ( sizeof(&npath) ) how to get the length. 我只是猜测不成功( sizeof(&npath) )如何获得长度。 I'm not well versed in C, but I figure there is a way to get a length out of a jstring. 我不太熟悉C,但是我认为有一种方法可以从jstring中获取长度。

Google yields nothing, what basic thing am I missing? Google无法产生任何收益,我最想念的是什么?

Since the type of the variable is const char * it suggests that it's a nul terminated string, hence 由于变量的类型为const char *这表明它是一个以nul结尾的字符串,因此

size_t length = strlen(npath);

should be enough. 应该足够了。

Although, your call to bind() is wrong, you shold pass the size of the address structure, for which 尽管您对bind()调用是错误的,但是您要通过传递地址结构的大小,为此

return bind(sockfd, sun, sizeof(sun));

should be correct. 应该是正确的。

First, you have a memory leak. 首先,您有内存泄漏。 The char* pointer returned by GetStringUTFChars() must be freed using ReleaseStringUTFChars() , which you are not doing. 必须使用ReleaseStringUTFChars()释放GetStringUTFChars()返回的char*指针,而您并没有这样做。

Second, bind() expects you to specify the byte size of the sockaddr_un struct, not the character length of npath . 其次, bind()期望您指定sockaddr_un结构的字节大小,而不是npath的字符长度。 Also, the second parameter of bind() expects a sockaddr* pointer as input. 另外, bind()的第二个参数需要一个sockaddr*指针作为输入。

Third, sockaddr_un::sun_path is a char[] array, you cannot assign a char* pointer to it. 第三, sockaddr_un::sun_path是一个char[]数组,您不能为其分配char*指针。 You have to copy the content that is being pointed at. 您必须复制所指向的内容。

Try this: 尝试这个:

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));
}

With that said, sockaddr_un always uses AF_UNIX for its family, so it does not make sense to pass a family as an input value. 话虽如此, sockaddr_un 始终AF_UNIX用于其系列,因此将family作为输入值传递没有意义。 If you need to pass in different family values, you need to use a different sockaddr_... struct for each family , eg: 如果需要传递不同的family价值观,则需要为每个family使用不同的sockaddr_...结构,例如:

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;
}

Regarding the length of the jstring, what is needed is GetStringUTFLength. 关于jstring的长度,需要的是GetStringUTFLength。

https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html

This should be more efficient than calling strlen on the null terminated char* as I don't think it will need to search for the final null. 这应该比对null终止的char *调用strlen更为有效,因为我认为它不需要搜索最终的null。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM