【问题标题】:Jna, Pointer already mapped to Proxy interfaceJna,指针已经映射到代理接口
【发布时间】:2016-10-20 14:24:27
【问题描述】:

我正在尝试做一个 openvr java bindingkotlin port 并将其更新到 1.0.3

我正在写IVRSystem struct/class

我手动编写了所有方法,以确保 Intellij 中的自动翻译器不会出现任何错误

我摆脱了来自 getFieldOrder() 的不同数量字段的所有错误,但现在我仍然收到错误:

Exception in thread "main" java.lang.IllegalStateException: Pointer native@0xffffffff already mapped to Proxy interface to native function@0xffffffff (IVRSystem$GetEyeToHeadTransform_callback).
Native code may be re-using a default function pointer, in which case you may need to use a common Callback class wherever the function pointer is reused.
    at com.sun.jna.CallbackReference.getCallback(CallbackReference.java:124)
    at com.sun.jna.CallbackReference.getCallback(CallbackReference.java:107)
    at com.sun.jna.Pointer.getValue(Pointer.java:430)
    at com.sun.jna.Structure.readField(Structure.java:705)
    at com.sun.jna.Structure.read(Structure.java:565)
    at IVRSystem.<init>(vr.kt:2091)
    at VrKt.VR_Init(vr.kt:2116)
    at VrKt.main(vr.kt:2133)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

根据this comment,似乎对特定回调(GetEyeToHeadTransform_callback?)有多次调用,但事实并非如此,我检查并仔细检查了代码,只有一个引用该回调..

还有什么可能?

编辑:

首先,当我在 IVRSysten 上课时read() 会发生这种情况,但我无法避免......

其次,我看到here前面的所有方法都得到了真实的地址,比如native@0x7fee4bebfd0,只有GetEyeToHeadTransform总是得到native@0xffffffff...

编辑2:

调查原始代码

dprintf("GetRecommendedRenderTargetSize %p\n", &vr::IVRSystem::GetRecommendedRenderTargetSize);
dprintf("GetProjectionMatrix %p\n", &vr::IVRSystem::GetProjectionMatrix);
dprintf("GetProjectionRaw %p\n", &vr::IVRSystem::GetProjectionRaw);
dprintf("ComputeDistortion %p\n", &vr::IVRSystem::ComputeDistortion);
dprintf("GetEyeToHeadTransform %p\n", &vr::IVRSystem::GetEyeToHeadTransform);
dprintf("GetTimeSinceLastVsync %p\n", &vr::IVRSystem::GetTimeSinceLastVsync);
dprintf("GetD3D9AdapterIndex %p\n", &vr::IVRSystem::GetD3D9AdapterIndex);
dprintf("GetDXGIOutputInfo %p\n", &vr::IVRSystem::GetDXGIOutputInfo);
dprintf("IsDisplayOnDesktop %p\n", &vr::IVRSystem::IsDisplayOnDesktop);
dprintf("SetDisplayVisibility %p\n", &vr::IVRSystem::SetDisplayVisibility);
dprintf("GetDeviceToAbsoluteTrackingPose %p\n", &vr::IVRSystem::GetDeviceToAbsoluteTrackingPose);
dprintf("ResetSeatedZeroPose %p\n", &vr::IVRSystem::ResetSeatedZeroPose);
dprintf("GetSeatedZeroPoseToStandingAbsoluteTrackingPose %p\n", &vr::IVRSystem::GetSeatedZeroPoseToStandingAbsoluteTrackingPose);

打印出来

GetRecommendedRenderTargetSize 0109871D
GetProjectionMatrix 0109AACC
GetProjectionRaw 0109AAD1
ComputeDistortion 0109AAF9
GetEyeToHeadTransform 0109AAC2
GetTimeSinceLastVsync 0109AAE5
GetD3D9AdapterIndex 0109AAF4
GetDXGIOutputInfo 0109AADB
IsDisplayOnDesktop 0109AAEA
SetDisplayVisibility 0109AAE0
GetDeviceToAbsoluteTrackingPose 0109AAEF
ResetSeatedZeroPose 0109AAD6
GetSeatedZeroPoseToStandingAbsoluteTrackingPose 0109AAC7

GetEyeToHeadTransformGetSeatedZeroPoseToStandingAbsoluteTrackingPose 有不同的指针..

【问题讨论】:

    标签: java kotlin jna openvr


    【解决方案1】:

    本机代码将-1 的“神奇”值用于多个回调签名。在编写此 JNA 的回调代码时,假设将相同的函数指针映射到两个不同的签名应该是错误的。

    我猜-1 值的意思类似于“使用默认回调”(可以说,简单的 NULL 指针可能就足够了,除非库使用 NULL 表示不调用回调)。

    当您看到-1 值时,您可以通过覆盖Structure.read()Structure.readField() 返回一个魔术值或常量回调对象来解决此问题,例如

    public void read() {
        Memory old = getPointer();
        Memory m = autoAllocate(size());
        // horribly inefficient, but it'll do
        m.write(0, old.getByteArray(0, size()), 0, size());
        useMemory(m);
        // Zero out the problematic callbacks
        for (field : problematic_fields) {
            m.setPointer(field_offset, null);
        }
        super.read();
        useMemory(old);
    }
    

    【讨论】:

    • 谢谢蒂莫西,我解决了as following,但现在我得到了另外两个带有0xfa0 的字段和另外几个带有另一个相同指针的字段......这不可能是一个错误在 jna 方面,不是吗?不管怎样,我在 Valve openvr github 上开了一个issue,让我们看看是怎么回事..
    • openvr 完全有可能只是重用了一个回调,或者它可能是另一个神奇的值(0xfa0 看起来不像一个有效的函数指针)。如果您实际上不需要设置或调用给定的回调,只需将其定义为 Pointer
    • 我解决了!不知何故你是对的,我使用"IVRSystem_012" 而不是"FnTable:IVRSystem_012" 实例化IVRSystem,所以库返回对我无用的回调指针..谢谢!
    【解决方案2】:

    尽管这是一个老问题,但我想分享我的经验。在我的情况下,我有一个本机对象,它作为映射了代理方法的结构传递给 Java。该对象是某种会话,它实现了一个应该删除本机对象本身的关闭方法。一旦调用 close 并删除本机对象,就会引发类似的异常。问题是在函数调用后 JNA 重新同步了已删除的本机对象。这可以通过将 auto read 设置为 false 来解决。

    public void close(Handler handler) {
        setAutoRead(false);
        close.invoke(this, handler);
        setAutoWrite(false);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 2021-11-26
      相关资源
      最近更新 更多