获取JNA中参数返回的不透明结构

时间:2017-05-17 23:21:35

标签: java c pointers struct jna

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

int findSomething(SomeStruct *s)

(具体来说,它是this method,我试图获得itemRef。还有一个使用示例here。)问题是我不知道SomeStruct有哪些字段或有多大字段。它只存在于传递给其他本机库函数。所以,我想要这样的东西(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),我想我可以使用JNA Memory来创建指针。我可以编写一个返回sizeof(SomeStruct)的本机方法,但我不想在我自己的代码中添加本机组件。

这与this question类似,但是它询问了SomeStruct字段在运行时是否已知的情况,而在我的情况下,字段被图书馆作者故意隐藏。< / p>

1 个答案:

答案 0 :(得分:2)

SecKeychainItemRef类型is defined to be a pointer to the struct。这意味着SecKeychainFindGenericPassword函数实际上需要一个指向的指针作为itemRef参数,因此,您可以使用JNA PointerByReference类作为参数。

成功通话后,您可以使用PointerByReference.getValue()获取不透明指针。

/* 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类。这会以更清晰的方式将参数的类型传递给读者,即使它不允许您访问结构的内部。