- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的任务是将 C# 应用程序迁移到 Java 应用程序。 C# 应用程序使用几个 DLL 来完成它的工作,与外围设备进行通信。
DLL 的 header 在 C# 中看起来像这样
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct InnerStructure
{
/// COM port used by the device
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = PORT_SIZE)] //7
public string szPort;
/// Specifies whether the device is activated.
public bool fActivated;
/// Name of the device
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_NAME_SIZE)] //248
public string szName; //COM
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct ParamStructure
{
/// COM port used by the devices
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public InnerStructure[] USB;
}
[DllImport("PCLService.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool startPclService();
[DllImport("PCLService.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool stopPclService();
[DllImport("PclUtilities.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern int getUSBDevices(ref ParamStructure pStructure, ref int pdwSize, ref int pdwEntries);
我最初尝试使用 JNI,但我无法加载 DLL(它们使用 .NET,并且很难找到 DependenciesWalker 的依赖项),所以我切换到 JNA。
这是我的 Java 代码
public class DllDemo {
@Structure.FieldOrder({ "szPort", "fActivated", "szName" })
public static class InnerStructure extends Structure {
public PointerByReference szPort;
public IntByReference fActivated;
public PointerByReference szName;
public InnerStructure() {};
public InnerStructure(Pointer p) {
super(p);
read();
};
}
@Structure.FieldOrder({ "USB" })
public static class ParamStructure extends Structure implements Structure.ByReference {
// In the C# code, the array is size 10
public InnerStructure[] USB = (InnerStructure[])new InnerStructure().toArray(10);
public ParamStructure() {};
public ParamStructure(Pointer p) {
super(p);
read();
};
}
public interface MyService extends Library {
MyService INSTANCE = (MyService) Native.load("C:\\IRD\\Documentacion\\VisaNet\\App PCL Demo VisaNet - V2.11\\x32\\PCLService.dll", MyService.class);
boolean startPclService();
boolean stopPclService();
}
public interface MyUtilities extends Library {
MyUtilities INSTANCE = (MyUtilities) Native.load("C:\\IRD\\Documentacion\\VisaNet\\App PCL Demo VisaNet - V2.11\\x32\\PclUtilities", MyUtilities.class);
int getUSBDevices(ParamStructure paramStructure, IntByReference pdwSize, IntByReference pdwEntries);
}
public static void main(String args[]) {
System.out.println("start");
MyService.INSTANCE.startPclService();
ParamStructure paramStructure = new ParamStructure();
paramStructure.write();
//This value is copied straightforward from the original code as well
int size = (248 + 8 + 7) * 10;
IntByReference pdwSize = new IntByReference(size);
IntByReference pdwEntries = new IntByReference(0);
int Ret2 = MyUtilities.INSTANCE.getUSBDevices(paramStructure, pdwSize, pdwEntries);
System.out.println("Ret2 = " + Ret2 + ", pdwEntries = " + pdwEntries.getValue());
if (pdwEntries.getValue() > 0) {
for (int i = 0 ; i < pdwEntries.getValue() ; i++) {
InnerStructure inner = paramStructure.USB[i];
inner.read();
System.out.println(i + " => " + inner.toString());
System.out.println("toString 1 => " + inner.szPort.toString());
System.out.println("toString 2 => " + inner.szPort.getPointer().toString());
System.out.println(">" + inner.szPort.getPointer().getString(0, "utf8") + "<");
}
}
paramStructure.clear();
MyService.INSTANCE.stopPclService();
System.out.println("stop");
}
}
这是输出。
start
Ret2 = 0, pdwEntries = 1
0 => DllDemo$InnerStructure(allocated@0x59b550 (12 bytes) (shared from auto-allocated@0x59b550 (120 bytes))) {
PointerByReference szPort@0x0=native@0x4f0043 (com.sun.jna.ptr.PointerByReference@4f0043)
IntByReference fActivated@0x4=native@0x35004d (com.sun.jna.ptr.IntByReference@35004d)
PointerByReference szName@0x8=null
}
toString 1 => native@0x4f0043 (com.sun.jna.ptr.PointerByReference@4f0043)
toString 2 => native@0x4f0043
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.getStringBytes(Native Method)
at com.sun.jna.Native.getString(Native.java:2224)
at com.sun.jna.Pointer.getString(Pointer.java:681)
at com.ingenico.DllDemo.main(DllDemo.java:65)
Process finished with exit code 1
第65行是这个
System.out.println(">" + inner.szPort.getPointer().getString(0, "utf8") + "<");
有时它不会给出错误,但字符串为空。我还没弄明白为什么会这样。
两个类中是否存在构造函数以及行 paramStructure.write() 和 inner.read() 没有区别。
无论值(value)如何,这就是它在 IntelliJ 调试器中的样子
我试过这样改变内部结构
public static class InnerStructure extends Structure implements Structure.ByReference {
public PointerByReference szPort;
public IntByReference fActivated;
public PointerByReference szName;
public InnerStructure() {};
public InnerStructure(Pointer p) { super(p); };
}
甚至像这样。
public static class InnerStructure extends Structure implements Structure.ByReference {
public String szPort;
public int fActivated;
public String szName;
public InnerStructure() {};
public InnerStructure(Pointer p) { super(p); };
}
在这两种情况下,我得到
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native._getPointer(Native Method)
at com.sun.jna.Native.getPointer(Native.java:2211)
at com.sun.jna.Pointer.getPointer(Pointer.java:642)
at com.sun.jna.Pointer.getValue(Pointer.java:390)
at com.sun.jna.Structure.readField(Structure.java:732)
at com.sun.jna.Structure.read(Structure.java:591)
at com.sun.jna.Structure.autoRead(Structure.java:2141)
at com.sun.jna.Structure.conditionalAutoRead(Structure.java:561)
at com.sun.jna.Structure.updateStructureByReference(Structure.java:690)
at com.sun.jna.Pointer.readArray(Pointer.java:492)
at com.sun.jna.Pointer.getValue(Pointer.java:450)
at com.sun.jna.Structure.readField(Structure.java:732)
at com.sun.jna.Structure.read(Structure.java:591)
at com.sun.jna.Structure.autoRead(Structure.java:2141)
at com.sun.jna.Function.invoke(Function.java:381)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy3.getUSBDevices(Unknown Source)
at com.ingenico.DllDemo.main(DllDemo.java:49) <- getUSBDevices
最佳答案
您没有正确映射字符串。
您已将 szPort
定义为 PointerByReference
,它是指向包含指针的内存位置的指针。然后您尝试使用 inner.szPort.getPointer()
调用它。那仍然是相同的“指向指针的指针”。 JNA 的一个很好的经验法则是,如果您正在使用 ByReference
类并且从不访问它的 getValue()
方法,那么您可能做错了什么。您的意思可能是 inner.szPort.getValue().getString(...)
。但这会失败,因为您实际上没有真正的指针。填充 szPort
元素的前 4 个字节实际上是 unicode 字符。
您已经定义了包含 3 个 4 字节元素(3 x 4 字节指针)的结构,总共 12 个字节(根据您的调试图像)。您实际上需要一个 7 个字符的固定宽度字符串、4 个字节的 boolean 值和 248 个字符的固定宽度字符串。如果您的编码是 ASCII,则为 259 个字节,或者在您的情况下,Unicode 字符串为 514 个字节。
查看您的调试图像,我们可以看到发生了什么。前 4 个字节包含 0x0043004f,您将其视为指针(地址 0x4f0043)并尝试从中读取数据。但它实际上是 unicode 字符 0x0043(“C”)和 0x004f(“O”)。当您尝试从该地址读取时,您并不拥有内存。如果幸运的话,内存为零并且您从未读取任何内容,并且您的代码返回一个零长度的空终止字符串。但是,如果该内存不是 null,则会出现错误。
接下来的 4 个字节是 0x004d0035,您将其称为 IntByReference“指针”(0x35004d),但它实际上是字符“M”和“5”。由于 szName
字段有一个空指针,接下来的 4 个字节似乎是 0x00000000 并且您已经命中了空终止符。所以它看起来像你的 szPort
字符串是“COM5”,隐藏在众目睽睽之下!
现在我们知道您的代码为什么会出错了。你如何修复它?
您的 C# 映射定义 szPort
的类型是 UnmanagedType.ByValTStr
,according to MS Docs , 是:
A fixed-length array of characters; the array's type is determined by the character set of the containing structure.
您可能需要该结构中的字节数组(您可以使用适当的编码将其放入 String
构造函数中),长度为 PORT_SIZE
x 字符宽度(如果您的编码是 ASCII,则为 1;对于 Unicode,则为 2)。您应该使用 charwidth x MAX_NAME_SIZE
类似地映射 szName
。
最后,IntByReference
也是一个指针(在您的系统上是 4 个字节),但 C# 中的原始变量是一个 bool
。如果不对其进行编码(marshal)处理,它会映射到 Windows BOOL
,这是一个普通的 4 字节 C int
。 Java 的 boolean
也是 4 个字节,所以你可以在这里使用它。所以你可能想要这样的东西:
int CHAR_WIDTH = W32APITypeMapper.DEFAULT == W32APITypeMapper.UNICODE ? 2 : 1;
int PORT_SIZE = 7;
int MAX_NAME_SIZE = 248;
class InnerStructure ... {
public byte[] szPort = new byte[CHAR_WIDTH * PORT_SIZE];
public boolean fActivated;
public byte[] szName = new byte[CHAR_WIDTH * MAX_NAME_SIZE];
...
}
关于java - JNA 从结构内的结构数组中读取无效的内存访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58700626/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!