请帮助我为 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 的对象?
您的
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
}
}