当前位置: 首页 > 知识库问答 >
问题:

JNA中的内存访问无效

干亮
2023-03-14

使用JNA时,我在调用QLConnect方法时收到无效内存访问错误。

下面是我映射DLL的接口:

import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;

public interface QuikLimit extends StdCallLibrary {
    
    QuikLimit INSTANCE = (QuikLimit) Native.load(new File("").getAbsolutePath() + "\\QuikLimit.dll", QuikLimit.class);
    
    int QLConnect(String userName, String userPassword, byte[] desc);
    
    //more methods from dll
}

我有另一个带有常量的类:

public class Const {
    public static final int DESC_SIZE = 1024;
    
    public enum Status {
        //enum values

        int code;

        private Status(int code) {
            this.code = code;
        }
        public int getCode() {
            return code;
        }
    };
}

以下是代码中出现的位置:

@Component
public class ConnectionManager {
    
    @Value("${quik.login}")
    private String login;
    @Value("${quik.password}")
    private String password;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private boolean connected;

    public synchronized BaseResponse connect() {
        BaseResponse result = new BaseResponse();
        byte[] desc = new byte[Const.DESC_SIZE]; 
        if (connected) {
        //logic if connected
        logger.info("call QLConnect");
        int retVal = QuikLimit.INSTANCE.QLConnect(login, password, desc);
        if (retVal == Const.Status.QL_ACTIVE.getCode()) {       
        //logic from response
        } else if (retVal == Const.Status.QL_CONNECTEDNOTACTIVE.getCode()) {
        //logic from response
        }
        result.setCode(retVal);
        result.setDescription(Util.descToStr(desc));
        QuikLimit.INSTANCE.QLDisconnect();
        return result;
    }
}

我知道1假设立即落在类型在dll中不匹配的事实上。但是头文件明确说明返回类型是int:

typedef __int32             ql_long;
ql_long _stdcall QLConnect(const char* lpszUserName, const char* lpszUserPassword, char* lpszError);

lpszUserName是指向包含用户名的ASCIIZ字符串的指针。

pszUserPassword是一个指向包含用户密码的ASCIIZ字符串的指针。

lpszDesc是一个指向缓冲区的指针,在出现错误的情况下,该缓冲区中的行及其描述。最小缓冲区大小为512字节。

还有什么可能是错误的原因?

共有1个答案

梁韬
2023-03-14

当您收到“无效内存访问”错误时,首先要检查的是您的类型映射,您正确地从查看int返回值开始。事实证明,其他参数的字符串映射在 *nix 系统上工作正常,需要在 Windows 上进行一些特殊处理。

默认情况下,Windows使用UTF 16编码,JNA的默认类型映射试图将Java<code>String</code>对象转换为UTF-16编码的本地字符串(<code>wchar*</code>)。这对于Windows API DLL很好。

但是,您的自定义DLL指定用户名和密码参数应该是ASCIIZ格式(以空字符结尾的C字符串)。

您可以通过在加载DLL时包含W32APIOptions.ASCII_OPTIONS作为第三个参数来强制JNA使用ASCIIString类型映射器,例如,

QuikLimit INSTANCE = (QuikLimit) Native.load(new File("").getAbsolutePath() + "\\QuikLimit.dll", QuikLimit.class, W32APIOptions.ASCII_OPTIONS);

还有其他更细粒度的方法只处理String类型映射,这些方法不会尝试也执行函数映射(如果任何映射的函数以W或A结尾,这可能会中断!您可以深入研究 W32APIOptions 类,了解如何创建自己的自定义选项来传递。

 类似资料:
  • 问题内容: 我已经从事Java项目一年了。我的代码已经工作了好几个月了。几天前,我在Mac(Snow Leopard 10.6.8)上将Java SDK升级到最新版本1.6.0_26。升级后,发生了一些非常奇怪的事情。当我运行某些类时,出现此错误: 位置0x202 rip = 0x202的无效内存访问 但是,如果我使用- Xint(已解释)运行它们,它们会工作,但速度较慢,但​​效果很好。我在使用

  • 问题内容: 我正在尝试直接为嵌入式Linux项目访问物理内存,但是我不确定如何最好地指定使用的内存。 如果我定期引导设备并访问/ dev / mem,则可以轻松地对其几乎任何位置进行读写。但是,在这种情况下,我正在访问可以轻松分配给任何进程的内存。我不想做 我的/ dev / mem代码是(删除了所有错误,等等。): 这可行。但是,我想使用没有其他人会碰到的内存。我尝试通过使用mem = XXXm

  • 我正在使用tess4j.jar编写一个程序。该程序正在从图像中提取文本及其位置。我得到这个错误: 有趣的是,它不会出现在每张图片上。有人知道我哪里出错了吗? 这是我的代码:

  • 我有一台在内部网8081端口上运行Nexus OSS存储库(版本3.15.1-01)的机器。我可以通过它的IP ping这台机器,我甚至Jenkins在8080端口上运行,可以通过任何互联网浏览器很好地访问它。然而,当我试图在8081上远程访问Nexus时,我只得到超时。 我已经在Nexus上配置了http/https代理(我们有一个公司代理),它可以毫无问题地从在线repos下载工件,并且我可以

  • 问题内容: 示例代码: 问题行: 错误: 题: 那么,如何访问该界面内的键? 我是否需要使用方法集定义更复杂的接口来完成此操作? 问题答案: 由于您的分片类型为,因此索引该分片将为您提供type的元素。类型的值无法建立索引。 但是由于您将类型的值放入其中,因此可以使用类型断言来获取该映射类型的值,您可以对其进行正确索引: 输出(在Go Playground上尝试): 如果您知道总是将类型的值存储在

  • 我正在尝试从intellij控制台访问内存中的H2数据库。我正在使用spring boot配置所有内容。连接字符串为:Spring。数据源。url=jdbc:h2:mem:testdb 当我使用intellij连接到数据库时,我看不到或查询表。我可以运行createtable命令来获取它,但仅此而已。这是该配置的图像: SHOW TABLES查询的结果不返回任何内容。 为什么我无法连接到此数据库?