如何正确描述Java JNA对象

问题描述 投票:0回答:1

请帮助我为 C 代码创建正确的 JNA 对象。 我有一个动态库 n2q_lib.dll 。该库使用其自己的配置文件以及可能位于同一目录中的其他库(外部开发人员的秘密)。该库仅使用 ASCII 支持(它不理解 UTF 字符串)和 x86 架构(我使用 Java x86)进行编译。

// C code example
// n2q_lib.h
#ifndef _N2Q_LIB_H_
#define _N2Q_LIB_H_
#include "n2q_msg.h"

extern "C" HN2QCONN __stdcall N2QLibConnCreate(LPCTSTR lpszIniFile, LPCTSTR lpszSection, N2Q_CALLBACK_PROC Callback);
extern "C" BOOL __stdcall N2QLibConnectQuik(HN2QCONN hConn);
extern "C" BOOL __stdcall N2QLibIsConnected(HN2QCONN hConn);

typedef HN2QCONN (_stdcall *N2QLIB_CONN_CREATE_DLL_FUNC)(LPCTSTR, LPCTSTR, N2Q_CALLBACK_PROC, int, int);
typedef BOOL (_stdcall *N2QLIB_CONNECT_QUIK_DLL_FUNC)(HN2QCONN);
typedef BOOL (_stdcall *N2QLIB_IS_CONNECTED_DLL_FUNC)(HN2QCONN);
#endif

// n2q_message.h
#ifndef _N2Q_MSG_H_
#define _N2Q_MSG_H_

struct N2Q_MESSAGE
{
    int     nSeverity;
    DWORD   dwCode;
    char    szMsg[512];
    N2Q_MESSAGE() {dwCode=0; nSeverity=0; memset(szMsg, 0, sizeof(szMsg)); };
    N2Q_MESSAGE& operator=(N2Q_MESSAGE& r) {
        if( this == &r ) return *this; 
        nSeverity=r.nSeverity;
        dwCode=r.dwCode;
        strcpy(szMsg, r.szMsg);
        return *this;
    }; 
    N2Q_MESSAGE(N2Q_MESSAGE& r) {*this=r;};
};

DECLARE_HANDLE (HN2QCONN);

typedef N2Q_CALLBACK_PROC (WINAPI *SET_CALLBACK_DLL_FUNC)(N2Q_CALLBACK_PROC);

// n2q_test.cpp
#include "stdafx.h"
#include "windows.h"
#include "n2q_lib.h"

#pragma comment (lib, "n2q_lib.lib")

int WINAPI CallbackProc(N2Q_MESSAGE* msg)
{
    printf("Sev=%d; Code=%d; Msg=%s\n", msg->nSeverity, msg->dwCode, msg->szMsg);
    return 1;
}

int main(int argc, char* argv[])
{
    HN2QCONN hConn = N2QLibConnCreate("C:\\Temp\\n2q.ini", "local", CallbackProc);
    
    if (!N2QLibConnectQuik(hConn))                                  
        printf("error connect to server.");

    if(!N2QLibIsConnected(hConn))                                   
        printf("error connect to server.");
}

编译示例C++代码后,连接成功!

我想编写 JNA 代码来调用这个本机库。

// Java
import com.sun.jna.*;

public class JavaCallback implements Callback {
    public int callback (N2q_message msg) {
        System.out.println(msg.szMsg);
        return 1;
    }
}

public class N2q_message extends Structure {
    int nSeverity;
    int dwCode;
    String szMsg = new String();
    public N2q_message() {
        dwCode=0; 
        nSeverity=0; 
        szMsg="";
    };
    public N2q_message(N2q_message r) {
        dwCode=r.dwCode; 
        nSeverity=r.nSeverity; 
        szMsg=r.szMsg;
    };
}

public interface N2q_lib extends StdCallLibrary  {
    N2q_lib INSTANCE = (N2q_lib) Native.load(
            "n2q_lib.dll"
            , N2q_lib.class
            , Collections.singletonMap(Library.OPTION_STRING_ENCODING, "Cp1251")
    );
    Pointer N2QLibConnCreate(String lpszIniFile, String lpszSection, JavaCallback Callback);
    boolean N2QLibConnectQuik(Pointer hConn);
    boolean N2QLibIsConnected(Pointer hConn);
}

public class App {
  public static void main(String[] args) throws InterruptedException {
    System.setProperty("jna.library.path", System.getProperty("user.dir")+"\\dll");
    System.setProperty("jna.encoding", "Cp1251");
      
    Pointer hConn = N2q_lib.INSTANCE.N2QLibConnCreate(
            System.getProperty("jna.library.path")+"\\n2q.ini"
            , "local"
            , new JavaCallback());
    System.out.println(System.getProperty("jna.library.path")+"\\n2q.ini");
    System.out.println(hConn);
    Thread.sleep(1000);
    if (N2q_lib.INSTANCE.N2QLibConnectQuik(hConn) != true)
        System.out.println("error connect to server.");
    if (N2q_lib.INSTANCE.N2QLibIsConnected(hConn) != true)
        System.out.println("error connect to server.");
  }
}

当我启动时,我收到连接错误:

C:\Users\123\myproject\dll\n2q.ini
native@0x5540598
error connect to server.
error connect to server.

为什么我无法连接?我是否错误地描述了 JNA 的对象?

java c jna
1个回答
0
投票

您的

N2q_message
类映射不正确。 JNA 使用反射来识别其字段,依赖于
public
修饰符和
FieldOrder
给出映射的顺序;您还没有公开这三个字段。

此外,原生映射还有一个固定长度的字符数组

char szMsg[512];
。这应该用字节数组映射。

此映射应该适用于结构:

@FieldOrder ({ "nSeverity", "dwCode", "szMsg" })
public class N2q_message extends Structure {
    public int nSeverity;
    public int dwCode;
    public byte[] szMsg = new byte[512];

    public N2q_message() {
        // no need to override the defaults
    }

    public N2q_message(N2q_message r) {
        nSeverity=r.nSeverity; 
        dwCode=r.dwCode; 
        szMsg=r.szMsg; // consider arraycopy here
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.