使用JNA调用IMMDeviceEnumerator返回S_FALSE及空指针引发异常
使用JNA调用Windows API获取音频端点时遇到S_FALSE和空指针问题
我正在用JNA结合Windows API开发,目标是调用MMDeviceEnumerator实例的GetDefaultAudioEndpoint方法获取MMDevice接口实例,但调用后返回HRESULT值为S_FALSE(1),得到的指针为空(null@0x2bd70eebeb0),后续基于该空指针调用IAudioEndpointVolume的Activate方法时触发NullPointerException。
运行时错误日志
Calling MMDeviceEnumerator.create() response: 0 Got MMDeviceEnumerator Pointer: native@0x2bd70f68590 Pointer.getPointer(): native@0x2bd70f68590 Calling mmEnumerator.GetDefaultAudioEndpoint(args) response: 1 Got mmDevice Pointer: null@0x2bd70eebeb0 Pointer.getValue(): null Pointer.getPointer(): allocated@0x2bd70eebeb0 (8 bytes) null Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.sun.jna.Pointer.getPointer(long)" because "vptr" is null at com.sun.jna.platform.win32.COM.COMInvoker._invokeNativeObject(COMInvoker.java:46) at spicey.IAudioEndpointVolume.Activate(App.java:76) at spicey.App.main(App.java:58)
完整程序代码
public final class App extends Unknown { public static final CLSID CLSID_IMMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e"); public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6"); public static final GUID IID_IAudioEndpointVolume = new GUID("5CDF2C82-841E-4546-9722-0CF74078229A"); public static final GUID IID_IAudioStreamVolume = new GUID("93014887-242D-4068-8A15-CF5E93B90FE3"); public static void main(String[] args) { Ole32.INSTANCE.CoInitializeEx(null, 0); // 0 is multi threaded System.out.println("Calling MMDeviceEnumerator.create()"); MMDeviceEnumerator mmEnumerator = MMDeviceEnumerator.create(); System.out.println("Got MMDeviceEnumerator"); System.out.println("Pointer: " + mmEnumerator.getPointer()); System.out.println("Pointer.getPointer(): " + mmEnumerator.getPointer()); System.out.println(); PointerByReference ppEndpoint = new PointerByReference(); System.out.println("Calling mmEnumerator.GetDefaultAudioEndpoint(args)"); mmEnumerator.GetDefaultAudioEndpoint(0, 0, ppEndpoint); System.out.println("Got mmDevice"); System.out.println("Pointer: " + ppEndpoint); System.out.println("Pointer.getValue(): " + ppEndpoint.getValue()); System.out.println("Pointer.getPointer(): " + ppEndpoint.getPointer()); System.out.println(); IAudioEndpointVolume iEndpoint = IAudioEndpointVolume.create(ppEndpoint.getPointer()); PointerByReference ppInterface = new PointerByReference(); iEndpoint.Activate(IID_IAudioEndpointVolume, WTypes.CLSCTX_ALL, ppInterface.getPointer()); } } class IAudioEndpointVolume extends Unknown { public IAudioEndpointVolume(Pointer p) { super(p); } public static IAudioEndpointVolume create(Pointer p) { return new IAudioEndpointVolume(p); } public void Activate(GUID iid, int dwClsCtx, Pointer ppInterface) { HRESULT res = (HRESULT) _invokeNativeObject(1, new Object[] { getPointer(), iid, dwClsCtx, null, ppInterface }, HRESULT.class); COMUtils.checkRC(res); } } class MMDeviceEnumerator extends Unknown { public static final CLSID CLSID_MMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e"); public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6"); public static interface Ole32 extends Library { Ole32 INSTANCE = (Ole32) Native.load("Ole32", Ole32.class); HRESULT CoCreateInstance(GUID rclsid, Pointer pUnkOuter, int dwClsContext, GUID riid, PointerByReference ppv); } public MMDeviceEnumerator(Pointer p) { super(p); } public static MMDeviceEnumerator create() { PointerByReference pEnumerator = new PointerByReference(); HRESULT hres = Ole32.INSTANCE.CoCreateInstance( CLSID_MMDeviceEnumerator, null, WTypes.CLSCTX_ALL, IID_IMMDeviceEnumerator, pEnumerator); System.out.println("response: " + hres); if (COMUtils.FAILED(hres)) { return null; } return new MMDeviceEnumerator(pEnumerator.getValue()); } // functionz public void GetDefaultAudioEndpoint(int dataFlow, int role, PointerByReference ppEndpoint) { HRESULT res = (HRESULT) _invokeNativeObject(2, new Object[] { getPointer(), dataFlow, role, ppEndpoint }, HRESULT.class); COMUtils.checkRC(res); System.out.println("response: " + res); } }
COMInvoker类代码
public abstract class COMInvoker extends PointerType { protected int _invokeNativeInt(int vtableId, Object[] args) { Pointer vptr = this.getPointer().getPointer(0); // we take the vtable id and multiply with the pointer size (4 bytes on // 32bit OS) Function func = Function.getFunction(vptr.getPointer(vtableId * Native.POINTER_SIZE)); return func.invokeInt(args); } protected Object _invokeNativeObject(int vtableId, Object[] args, Class<?> returnType) { Pointer vptr = this.getPointer().getPointer(0); // we take the vtable id and multiply with the pointer size (4 bytes on // 32bit OS) Function func = Function.getFunction(vptr.getPointer(vtableId * Native.POINTER_SIZE)); return func.invoke(returnType, args); } protected void _invokeNativeVoid(int vtableId, Object[] args) { Pointer vptr = this.getPointer().getPointer(0); // we take the vtable id and multiply with the pointer size (4 bytes on // 32bit OS) Function func = Function.getFunction(vptr.getPointer(vtableId * Native.POINTER_SIZE)); func.invokeVoid(args); } }
已经检查过COMInvoker类但未找到问题所在,恳请提供解决方案。
内容的提问来源于stack exchange,提问作者Spicey
相关产品推荐
相关产品推荐

