在JNA中获取参数返回的不透明结构 [英] Getting an opaque struct returned by parameter in JNA

查看:116
本文介绍了在JNA中获取参数返回的不透明结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Apple的Security.h框架中调用通过引用返回结构的方法,如下所示:

I'm trying to call a method in Apple's Security.h framework that returns a struct by reference, like so:

int findSomething(SomeStruct *s)

(具体来说,它是此方法,我我正在尝试获取itemRef.有一个用法示例

(Specifically, it's this method, and I'm trying to get itemRef. There's a usage example here.) The problem is that I don't know what fields SomeStruct has or how big it is. It only exists to be passed to other native library functions. So, I want something like this (Java):

interface SomeLib extends Library {
    int findSomething(Pointer p);
}

...
Pointer p = ... // Not sure how to make this
nativeLib.findSomething(p)
// Do something with p

我想,如果我可以在Java中执行sizeof(SomeStruct),则可以使用JNAs Memory创建指针.我可以编写一个本机方法来返回sizeof(SomeStruct),但是我不想在自己的代码中添加本机组件.

If I could do sizeof(SomeStruct) in Java, I could create the pointer using JNAs Memory, I think. I could write a native method to return sizeof(SomeStruct), but I don't want to add a native component to my own code.

这类似于此问题,但它询问了SomeStruct的字段在运行时是已知的,而就我而言,这些字段被库作者有意遮盖了.

This is similar to this question, but it asks about a case where the fields of SomeStruct are known at runtime, whereas, in my case, the fields are obscured intentionally by the library authors.

推荐答案

SecKeychainItemRef类型

The SecKeychainItemRef type is defined to be a pointer to the struct. This means that the SecKeychainFindGenericPassword function actually expects a pointer to a pointer as the itemRef argument, and as such, you can use the JNA PointerByReference class as the argument.

成功拨打电话后,您可以使用 PointerByReference.getValue() 以获得不透明的指针.

After a successful call, you can use PointerByReference.getValue() to get the opaque pointer.

/* int SecKeychainFindGenericPassword(
 *     Pointer keychainOrArray,
 *     int serviceNameLength,
 *     String serviceName,
 *     int accountNameLength,
 *     String accountName,
 *     IntByReference *passwordLength,
 *     PointerByReference passwordData,
 *     PointerByReference itemRef
 * );
 */

static void main() {
    IntByReference passLength = new IntByReference(0);
    PointerByReference passwordData = new PointerByReference();
    PointerByReference itemRef = new PointerByReference();

    int result = SecKeychainFindGenericPassword(
        keychainOrArray,
        "service name".length(),
        "service name",
        "account".length(),
        "account",
        passLength,
        passwordData,
        itemRef
    );

    if (result == 0) {
        System.out.printf(
            "OSStatus: %d, passDataPtr: 0x%08X, itemRefPtr: 0x%08X%n",
            result,
            Pointer.nativeValue(passwordData.getValue()),
            Pointer.nativeValue(itemRef.getValue())
        );
    } else {
        /* Use SecCopyErrorMessageString to get a human-readable message */
        System.out.printf("An error occurred: %d%n", result);
    }
}

如果在实际项目中调用此方法,建议创建一个名为SecKeychainItemRef的类,该类扩展了PointerByReference类.即使无法让您访问结构的内部结构,也可以以更清晰的方式将参数的类型传达给阅读器.

If you're calling this method in an actual project, I would suggest creating a class named SecKeychainItemRef which extends the PointerByReference class. This communicates the argument's type to the reader in a clearer fashion, even if it doesn't let you access the internals of the struct.

这篇关于在JNA中获取参数返回的不透明结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆