gpt4 book ai didi

Java JNA编写win32 API的自定义COM接口(interface)

转载 作者:太空宇宙 更新时间:2023-11-04 09:27:33 24 4
gpt4 key购买 nike

我需要编写 win32 API 的自定义 IShellFolder 接口(interface)。但我在调用方法 ParseDisplayName 时遇到问题。 jna 的原始版本有一个 bug,该方法的 pszDisplayName 参数是 String,但 win32 api 的参数是 wstring。

这是我的代码

String file = "c:\\Users\\Duchon\\Downloads\\Baumüller Brno, s.r.o.PS43668.prpkg";
PointerByReference psfDesktopPTR = new PointerByReference();
WinNT.HRESULT hResult = Shell32.INSTANCE.SHGetDesktopFolder(psfDesktopPTR);
if (COMUtils.SUCCEEDED(hResult)) {
IntByReference pcheaten = new IntByReference();
PointerByReference ppidl = new PointerByReference();
IntByReference pdwAttributes = new IntByReference();
IShellFolder psfDesktop = IShellFolder.Converter.PointerToIShellFolder(psfDesktopPTR);
hResult = psfDesktop.ParseDisplayName(null, null, new WString(file), pcheaten, ppidl, pdwAttributes);
if (COMUtils.SUCCEEDED(hResult)) {
}
}

这是我的 IShellFolder 界面:

public interface IShellFolder {
WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName, IntByReference pchEaten, PointerByReference ppidl, IntByReference pdwAttributes);

public static class Converter {
public static IShellFolder PointerToIShellFolder(final PointerByReference ptr) {
final Pointer interfacePointer = ptr.getValue();
final Pointer vTablePointer = interfacePointer.getPointer(0);
final Pointer[] vTable = new Pointer[1];
vTablePointer.read(0, vTable, 0, 1);
return new IShellFolder() {
@Override
public WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName, IntByReference pchEaten, PointerByReference ppidl, IntByReference pdwAttributes) {
Function f = Function.getFunction(vTable[0], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] {interfacePointer, hwnd, pbc, pszDisplayName, pchEaten, ppidl, pdwAttributes }));
}
};
}
}
}

并调用ParseDisplay方法抛出异常java.lang.Error:无效的内存访问。

当我遇到错误时你能帮助我吗?

非常感谢。

最佳答案

你就快到了。一般来说,定制现有 JNA 接口(interface)的方法是定义自己的接口(interface)并扩展它,然后编写自己的方法。对于单个方法,您基本上已完成,但 Converter 类会生成一个匿名类,您需要完全复制该类。这应该可行。

public interface MyIShellFolder extends com.sun.jna.platform.win32.COM.IShellFolder {

// Define your own function invocation.
// Since your argument signature includes a WString
// it will be an overloaded version selected when you use the
// WString argument.
WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName, IntByReference pchEaten,
PointerByReference ppidl, IntByReference pdwAttributes);

// Do the same extending the inner class
public static class Converter extends com.sun.jna.platform.win32.COM.IShellFolder.Converter {
// You are overriding the superclass version of this so you have
// to define the entire method
public static MyIShellFolder PointerToIShellFolder(final PointerByReference ptr) {
final Pointer interfacePointer = ptr.getValue();
final Pointer vTablePointer = interfacePointer.getPointer(0);
final Pointer[] vTable = new Pointer[13];
vTablePointer.read(0, vTable, 0, 13);
return new MyIShellFolder() {

@Override
public WinNT.HRESULT QueryInterface(REFIID byValue, PointerByReference pointerByReference) {
Function f = Function.getFunction(vTable[0], Function.ALT_CONVENTION);
return new WinNT.HRESULT(
f.invokeInt(new Object[] { interfacePointer, byValue, pointerByReference }));
}

@Override
public int AddRef() {
Function f = Function.getFunction(vTable[1], Function.ALT_CONVENTION);
return f.invokeInt(new Object[] { interfacePointer });
}

public int Release() {
Function f = Function.getFunction(vTable[2], Function.ALT_CONVENTION);
return f.invokeInt(new Object[] { interfacePointer });
}

@Override
public WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName,
IntByReference pchEaten, PointerByReference ppidl, IntByReference pdwAttributes) {
Function f = Function.getFunction(vTable[3], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, hwnd, pbc, pszDisplayName,
pchEaten, ppidl, pdwAttributes }));
}

@Override
public WinNT.HRESULT EnumObjects(WinDef.HWND hwnd, int grfFlags, PointerByReference ppenumIDList) {
Function f = Function.getFunction(vTable[4], Function.ALT_CONVENTION);
return new WinNT.HRESULT(
f.invokeInt(new Object[] { interfacePointer, hwnd, grfFlags, ppenumIDList }));
}

public WinNT.HRESULT BindToObject(Pointer pidl, Pointer pbc, REFIID riid, PointerByReference ppv) {
Function f = Function.getFunction(vTable[5], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, pidl, pbc, riid, ppv }));
}

@Override
public HRESULT BindToStorage(Pointer pidl, Pointer pbc, REFIID riid, PointerByReference ppv) {
Function f = Function.getFunction(vTable[6], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, pidl, pbc, riid, ppv }));
}

@Override
public HRESULT CompareIDs(WinDef.LPARAM lParam, Pointer pidl1, Pointer pidl2) {
Function f = Function.getFunction(vTable[7], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, lParam, pidl1, pidl2 }));
}

@Override
public HRESULT CreateViewObject(WinDef.HWND hwndOwner, REFIID riid, PointerByReference ppv) {
Function f = Function.getFunction(vTable[8], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, hwndOwner, riid, ppv }));
}

@Override
public HRESULT GetAttributesOf(int cidl, Pointer apidl, IntByReference rgfInOut) {
Function f = Function.getFunction(vTable[9], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, cidl, apidl, rgfInOut }));
}

@Override
public HRESULT GetUIObjectOf(WinDef.HWND hwndOwner, int cidl, Pointer apidl, REFIID riid,
IntByReference rgfReserved, PointerByReference ppv) {
Function f = Function.getFunction(vTable[10], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(
new Object[] { interfacePointer, hwndOwner, cidl, apidl, riid, rgfReserved, ppv }));
}

public WinNT.HRESULT GetDisplayNameOf(Pointer pidl, int flags, STRRET pName) {
Function f = Function.getFunction(vTable[11], Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, pidl, flags, pName }));
}

@Override
public HRESULT SetNameOf(WinDef.HWND hwnd, Pointer pidl, String pszName, int uFlags,
PointerByReference ppidlOut) {
Function f = Function.getFunction(vTable[12], Function.ALT_CONVENTION);
return new WinNT.HRESULT(
f.invokeInt(new Object[] { interfacePointer, hwnd, pidl, pszName, uFlags, ppidlOut }));
}

// OLD VERSION THAT YOU WANT TO IGNORE BUT MUST DECLARE
@Override
public HRESULT ParseDisplayName(HWND hwnd, Pointer pbc, String pszDisplayName, IntByReference pchEaten,
PointerByReference ppidl, IntByReference pdwAttributes) {
return null;
}
};
}
}
}

关于Java JNA编写win32 API的自定义COM接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57493294/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com