JNA 调用 Win32 API 方法 IShellFolder::GetUIObjectOf
JNA call Win32 API method IShellFolder::GetUIObjectOf
我在调用此方法时遇到问题 IShellFolder::GetUIObject 我不知道如何创建指向指针数组的指针作为此函数的第三个参数。在文档中这个函数的 header 是:
HRESULT GetUIObjectOf(
HWND hwndOwner,
UINT cidl,
PCUITEMID_CHILD_ARRAY apidl,
REFIID riid,
UINT *rgfReserved,
void **ppv
);
这是我的代码:
String directory = "c:\Users";
String file = "c:\Users\Duchon\Downloads\Baumüller Brno, s.r.o.PS43668.prpkg";
try {
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();
MyIShellFolder psfDesktop = MyIShellFolder.Converter.PointerToIShellFolder(psfDesktopPTR);
hResult = psfDesktop.ParseDisplayName(null, null, new WString(file), pcheaten, ppidl, pdwAttributes);
PointerByReference iContextMenuPtr = new PointerByReference();
if (COMUtils.SUCCEEDED(hResult)) {
Pointer[] ppidls = new Pointer[1];
ppidls[0] = ppidl.getValue();
hResult = psfDesktop.GetUIObjectOf(null, 1, ppidl.getValue(), new Guid.REFIID(IContextMenu.IID_IContextMenu), new IntByReference(), iContextMenuPtr);
if (COMUtils.SUCCEEDED(hResult)) {
// QueryIContextMenu ...
}
}
}
}
catch (Exception e) {
e.printStackTrace(System.err);
}
但是我得到无效内存访问异常。我需要一个文件数组的解决方案,而不仅仅是一个文件。非常感谢。
当您收到无效内存访问错误时,这表明您需要正确分配本机内存。您上面的代码只声明了一个 Java 端指针数组。
C 中的数组使用连续内存。这意味着您必须为数组分配一个足够大的本地内存块;收集一堆单独的分配是不够的(这就是在 Java 中声明单个 Pointer
变量所做的)。
分配本机内存块有两个主要选项:
选项 1. 使用 JNA 的 Memory
class 显式分配您需要的内存大小。如果您分配一个指针数组,您将像这样分配: Memory m = new Memory(numberOfElements * Native.POINTER_SIZE);
当您将返回值放入该内存中时,您将使用偏移量从数组中提取适当的指针,例如,对于索引为 0 的 [=第 16=] 个指针,执行 Pointer p = m.getPointer(i * Native.POINTER_SIZE);
选项 2. 创建适当大小的 Structure
(在本例中,包含一个指针元素)并使用 Structure.toArray()
分配结构数组。所以你可以定义:
@FieldOrder ({"childId"})
class PCUITEMID_CHILD extends Structure {
public Pointer childId;
}
然后分配数组
PCUITEM_CHILD[] pcuItemIdArray = new PCUITEMID_CHILD().toArray(numberOfElements);
然后你可以传递这个数组变量,并使用传统的数组语法访问它的结果。
Pointer p = pcuItemIdArray[0].childId;
我在调用此方法时遇到问题 IShellFolder::GetUIObject 我不知道如何创建指向指针数组的指针作为此函数的第三个参数。在文档中这个函数的 header 是:
HRESULT GetUIObjectOf(
HWND hwndOwner,
UINT cidl,
PCUITEMID_CHILD_ARRAY apidl,
REFIID riid,
UINT *rgfReserved,
void **ppv
);
这是我的代码:
String directory = "c:\Users";
String file = "c:\Users\Duchon\Downloads\Baumüller Brno, s.r.o.PS43668.prpkg";
try {
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();
MyIShellFolder psfDesktop = MyIShellFolder.Converter.PointerToIShellFolder(psfDesktopPTR);
hResult = psfDesktop.ParseDisplayName(null, null, new WString(file), pcheaten, ppidl, pdwAttributes);
PointerByReference iContextMenuPtr = new PointerByReference();
if (COMUtils.SUCCEEDED(hResult)) {
Pointer[] ppidls = new Pointer[1];
ppidls[0] = ppidl.getValue();
hResult = psfDesktop.GetUIObjectOf(null, 1, ppidl.getValue(), new Guid.REFIID(IContextMenu.IID_IContextMenu), new IntByReference(), iContextMenuPtr);
if (COMUtils.SUCCEEDED(hResult)) {
// QueryIContextMenu ...
}
}
}
}
catch (Exception e) {
e.printStackTrace(System.err);
}
但是我得到无效内存访问异常。我需要一个文件数组的解决方案,而不仅仅是一个文件。非常感谢。
当您收到无效内存访问错误时,这表明您需要正确分配本机内存。您上面的代码只声明了一个 Java 端指针数组。
C 中的数组使用连续内存。这意味着您必须为数组分配一个足够大的本地内存块;收集一堆单独的分配是不够的(这就是在 Java 中声明单个 Pointer
变量所做的)。
分配本机内存块有两个主要选项:
选项 1. 使用 JNA 的 Memory
class 显式分配您需要的内存大小。如果您分配一个指针数组,您将像这样分配: Memory m = new Memory(numberOfElements * Native.POINTER_SIZE);
当您将返回值放入该内存中时,您将使用偏移量从数组中提取适当的指针,例如,对于索引为 0 的 [=第 16=] 个指针,执行 Pointer p = m.getPointer(i * Native.POINTER_SIZE);
选项 2. 创建适当大小的 Structure
(在本例中,包含一个指针元素)并使用 Structure.toArray()
分配结构数组。所以你可以定义:
@FieldOrder ({"childId"})
class PCUITEMID_CHILD extends Structure {
public Pointer childId;
}
然后分配数组
PCUITEM_CHILD[] pcuItemIdArray = new PCUITEMID_CHILD().toArray(numberOfElements);
然后你可以传递这个数组变量,并使用传统的数组语法访问它的结果。
Pointer p = pcuItemIdArray[0].childId;