获取 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。