我如何使用更具体的结构类型来代替更通用的结构类型?
How do I use a more specific struct type in place of a more general one?
我正在开发 windows 设备管理器,它将与 java 一起使用。
我坚持尝试无错误地通过 SetupDiSetClassInstallParams 函数。 (我正在尝试禁用设备。)
我在 C++ 中 运行 完全相同的结构(必要方式),我没有任何问题。
我收到 ERROR_INVALID_USER_BUFFER 错误。当我尝试在 C++ 中得到这个错误时,我需要用错误的值更改 SP_PROPCHANGE_PARAMS 结构值。
我的结构减量:
public static class SP_CLASSINSTALL_HEADER extends Structure {
public static class ByReference extends SP_CLASSINSTALL_HEADER implements Structure.ByReference {
public ByReference() {
}
public ByReference(Pointer memory) {
super(memory);
}
}
public SP_CLASSINSTALL_HEADER() {
cbSize = size();
}
public SP_CLASSINSTALL_HEADER(Pointer memory) {
super(memory);
read();
}
public int cbSize;
public long InstallFunction; **/* <-- this should be int or else buffer size changes, dll cannot place variables on right places. */**
protected List getFieldOrder() {
return Arrays.asList(new String[] { "cbSize", "InstallFunction" });
}
}
public static class SP_PROPCHANGE_PARAMS extends Structure {
public static class ByReference extends SP_PROPCHANGE_PARAMS implements Structure.ByReference {
public ByReference() {
}
public ByReference(Pointer memory) {
super(memory);
}
}
public SP_PROPCHANGE_PARAMS() {
}
public SP_PROPCHANGE_PARAMS(Pointer memory) {
super(memory);
read();
}
public SP_CLASSINSTALL_HEADER ClassInstallHeader = new SP_CLASSINSTALL_HEADER();
public int StateChange;
public int Scope;
public int HwProfile;
protected List getFieldOrder() {
return Arrays.asList(new String[] { "ClassInstallHeader", "StateChange", "Scope", "HwProfile" });
}
}
我的函数减速:
boolean SetupDiSetClassInstallParams(WinNT.HANDLE hDevInfo, Pointer deviceInfoData, Pointer classInstallHeader, int size);
如何调用这个函数:
SP_PROPCHANGE_PARAMS spPropChangeParams = new SP_PROPCHANGE_PARAMS();
spPropChangeParams.ClassInstallHeader.InstallFunction = DISetupApi.DIF_PROPERTYCHANGE;
spPropChangeParams.Scope = DISetupApi.DICS_FLAG_GLOBAL;
spPropChangeParams.HwProfile = 0;
spPropChangeParams.StateChange = DISetupApi.DICS_DISABLE;
int spPropChangeParamsSize = spPropChangeParams.size();
SP_CLASSINSTALL_HEADER classInstallHeaderReference = new SP_CLASSINSTALL_HEADER(spPropChangeParams.getPointer());
setupApi.SetupDiSetClassInstallParams(hDevInfo, device.getSPDeviceInfoData().getPointer(), classInstallHeaderReference.getPointer(),
spPropChangeParamsSize);
它在 C++ 中的工作原理:
SP_PROPCHANGE_PARAMS spPropChangeParams;
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
spPropChangeParams.Scope = DICS_FLAG_GLOBAL;
spPropChangeParams.HwProfile = 0;
spPropChangeParams.StateChange = DICS_DISABLE;
SetupDiSetClassInstallParams(hDeviceInfo, &device.getDeviceInfoData(), (SP_CLASSINSTALL_HEADER*)&spPropChangeParams, sizeof(spPropChangeParams));
实际上我混合和匹配了太多的方式,这些结构和函数我改变了结构的变量类型和函数的参数类型,最后除了错误我什么也得不到。我找不到我的错误。你能帮我解决这个问题吗?
提前致谢!
传递 Structure
时,除非万不得已,否则不要使用 Structure.getPointer()
。当您这样做时,JNA 无法自动同步本机数据和 Java 数据,而且很容易出错,您需要自己记住在哪里做这件事。在您的情况下, Java 字段中的任何内容都不会在您调用 setupApi.SetupDiSetClassInstallParams
.
时复制到本机内存中
将您的函数映射更改为此:
boolean SetupDiSetClassInstallParams(WinNT.HANDLE hDevInfo, SP_DEVINFO_DATA deviceInfoData, SP_CLASSINSTALL_HEADER classInstallHeader, int size);
并将调用更改为:
setupApi.SetupDiSetClassInstallParams(hDevInfo, device.getSPDeviceInfoData(), classInstallHeaderReference, spPropChangeParamsSize);
编辑
如果你坚持你原来的结构定义(其中SP_CLASSINSTALL_HEADER
是一个字段),你需要添加一个函数映射到接口(扩展接口并创建你自己的本地库实例):
public interface MySetupApi extends SetupApi {
MySetupApi INSTANCE = (MySetupApi)Native.loadLibrary(MySetupApi.class, W32APIOptions.DEFAULT_OPTIONS);
boolean SetupDiSetClassInstallParams(WinNT.HANDLE hDevInfo, SP_DEVINFO_DATA deviceInfoData, SP_PROPCHANGE_PARAMS propChangeParams, int size);
}
我正在开发 windows 设备管理器,它将与 java 一起使用。 我坚持尝试无错误地通过 SetupDiSetClassInstallParams 函数。 (我正在尝试禁用设备。)
我在 C++ 中 运行 完全相同的结构(必要方式),我没有任何问题。
我收到 ERROR_INVALID_USER_BUFFER 错误。当我尝试在 C++ 中得到这个错误时,我需要用错误的值更改 SP_PROPCHANGE_PARAMS 结构值。
我的结构减量:
public static class SP_CLASSINSTALL_HEADER extends Structure {
public static class ByReference extends SP_CLASSINSTALL_HEADER implements Structure.ByReference {
public ByReference() {
}
public ByReference(Pointer memory) {
super(memory);
}
}
public SP_CLASSINSTALL_HEADER() {
cbSize = size();
}
public SP_CLASSINSTALL_HEADER(Pointer memory) {
super(memory);
read();
}
public int cbSize;
public long InstallFunction; **/* <-- this should be int or else buffer size changes, dll cannot place variables on right places. */**
protected List getFieldOrder() {
return Arrays.asList(new String[] { "cbSize", "InstallFunction" });
}
}
public static class SP_PROPCHANGE_PARAMS extends Structure {
public static class ByReference extends SP_PROPCHANGE_PARAMS implements Structure.ByReference {
public ByReference() {
}
public ByReference(Pointer memory) {
super(memory);
}
}
public SP_PROPCHANGE_PARAMS() {
}
public SP_PROPCHANGE_PARAMS(Pointer memory) {
super(memory);
read();
}
public SP_CLASSINSTALL_HEADER ClassInstallHeader = new SP_CLASSINSTALL_HEADER();
public int StateChange;
public int Scope;
public int HwProfile;
protected List getFieldOrder() {
return Arrays.asList(new String[] { "ClassInstallHeader", "StateChange", "Scope", "HwProfile" });
}
}
我的函数减速:
boolean SetupDiSetClassInstallParams(WinNT.HANDLE hDevInfo, Pointer deviceInfoData, Pointer classInstallHeader, int size);
如何调用这个函数:
SP_PROPCHANGE_PARAMS spPropChangeParams = new SP_PROPCHANGE_PARAMS();
spPropChangeParams.ClassInstallHeader.InstallFunction = DISetupApi.DIF_PROPERTYCHANGE;
spPropChangeParams.Scope = DISetupApi.DICS_FLAG_GLOBAL;
spPropChangeParams.HwProfile = 0;
spPropChangeParams.StateChange = DISetupApi.DICS_DISABLE;
int spPropChangeParamsSize = spPropChangeParams.size();
SP_CLASSINSTALL_HEADER classInstallHeaderReference = new SP_CLASSINSTALL_HEADER(spPropChangeParams.getPointer());
setupApi.SetupDiSetClassInstallParams(hDevInfo, device.getSPDeviceInfoData().getPointer(), classInstallHeaderReference.getPointer(),
spPropChangeParamsSize);
它在 C++ 中的工作原理:
SP_PROPCHANGE_PARAMS spPropChangeParams;
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
spPropChangeParams.Scope = DICS_FLAG_GLOBAL;
spPropChangeParams.HwProfile = 0;
spPropChangeParams.StateChange = DICS_DISABLE;
SetupDiSetClassInstallParams(hDeviceInfo, &device.getDeviceInfoData(), (SP_CLASSINSTALL_HEADER*)&spPropChangeParams, sizeof(spPropChangeParams));
实际上我混合和匹配了太多的方式,这些结构和函数我改变了结构的变量类型和函数的参数类型,最后除了错误我什么也得不到。我找不到我的错误。你能帮我解决这个问题吗?
提前致谢!
传递 Structure
时,除非万不得已,否则不要使用 Structure.getPointer()
。当您这样做时,JNA 无法自动同步本机数据和 Java 数据,而且很容易出错,您需要自己记住在哪里做这件事。在您的情况下, Java 字段中的任何内容都不会在您调用 setupApi.SetupDiSetClassInstallParams
.
将您的函数映射更改为此:
boolean SetupDiSetClassInstallParams(WinNT.HANDLE hDevInfo, SP_DEVINFO_DATA deviceInfoData, SP_CLASSINSTALL_HEADER classInstallHeader, int size);
并将调用更改为:
setupApi.SetupDiSetClassInstallParams(hDevInfo, device.getSPDeviceInfoData(), classInstallHeaderReference, spPropChangeParamsSize);
编辑
如果你坚持你原来的结构定义(其中SP_CLASSINSTALL_HEADER
是一个字段),你需要添加一个函数映射到接口(扩展接口并创建你自己的本地库实例):
public interface MySetupApi extends SetupApi {
MySetupApi INSTANCE = (MySetupApi)Native.loadLibrary(MySetupApi.class, W32APIOptions.DEFAULT_OPTIONS);
boolean SetupDiSetClassInstallParams(WinNT.HANDLE hDevInfo, SP_DEVINFO_DATA deviceInfoData, SP_PROPCHANGE_PARAMS propChangeParams, int size);
}