使用 JNA 调用 IMMDeviceEnumerator 方法返回 S_FALSE 和空(?)指针

问题描述 投票:0回答:1

我真的不知道如何表达这个问题(抱歉)。但基本上(使用 JNA 和 Windows API)我试图通过在我的 MMDeviceEnumerator 实例(?)上调用 GetDefaultAudioEndpoint 来获取 mmDevice 接口的实例(?)。问题是对 GetDefaultAudioEndpoint 的调用返回了我认为是空指针

null@0x2bd70eebeb0
。我认为这会导致稍后调用它在运行时产生此错误:

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)

对 GetDefaultAudioEndpoint 的调用还会返回 S_FALSE 或 1 的 HRESULT(如果有帮助的话)。 无论如何,这是完整的程序。我也很乐意提供任何额外信息。预先感谢!

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);
    }

}
java pointers winapi jna
1个回答
0
投票

Nvm我解决了。上面的代码有一些问题,但主要的一个是表id全部关闭,因为我忘记考虑到IMMDeviceEnumerator接口从IUnknown接口继承了3个方法,所以你必须为每个表id添加3争论。

© www.soinside.com 2019 - 2024. All rights reserved.