Jna, указатель уже сопоставлен с интерфейсом прокси
Я пытаюсь сделать порт kotlin Java-привязки openvr, а также обновлять его до 1.0.3
Я получил в момент написания IVRSystem
структура / класс
Я написал все методы вручную, чтобы быть уверенным, что не будет никакой ошибки от автоматического переводчика в 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)
Согласно этому комментарию, похоже, что есть несколько вызовов для определенного обратного вызова (GetEyeToHeadTransform_callback
?), но это не так, я проверил и дважды проверил код, есть одна и только одна ссылка на этот обратный вызов..
Что еще это может быть?
Редактировать:
во-первых, это происходит, когда я read()
на IVRSysten
класс, но я не могу избежать этого...
во-вторых, я вижу, что здесь все предыдущие методы получают реальные адреса, такие как native@0x7fee4bebfd0
, только GetEyeToHeadTransform
получает всегда native@0xffffffff
...
Edit2:
исследуя оригинальный код
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
GetEyeToHeadTransform
а также GetSeatedZeroPoseToStandingAbsoluteTrackingPose
есть разные указатели..
1 ответ
Нативный код использует "магическое" значение -1
для более чем одной подписи обратного вызова. Когда этот код обратного вызова для JNA был написан, предполагалось, что наличие одного и того же указателя функции для сопоставления с двумя разными сигнатурами должно быть ошибкой.
Я предполагаю, что -1
Значение означает что-то вроде "использовать обратный вызов по умолчанию" (когда, возможно, достаточно простого указателя NULL, если библиотека не использует NULL, чтобы указать, что вызов не вызывается).
Вы можете обойти это, переопределив Structure.read()
или же Structure.readField()
вернуть магическое значение или постоянный объект обратного вызова, когда вы видите -1
значение, например
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);
}
Несмотря на то, что это старый вопрос, я хотел бы поделиться своим опытом. В моем случае у меня есть собственный объект, который передается в Java как структура с сопоставленными методами прокси. Объект - это своего рода сеанс, который реализует метод закрытия, который должен удалить сам собственный объект. Как только вызывается close и удаляется собственный объект, генерируется аналогичное исключение. Проблема в том, что после вызова функции JNA повторно синхронизирует удаленный собственный объект. Это можно решить, установив для автоматического чтения значение false.
public void close(Handler handler) {
setAutoRead(false);
close.invoke(this, handler);
setAutoWrite(false);
}