将函数指针的 C 结构体转换为 JNA 代码
Posted
技术标签:
【中文标题】将函数指针的 C 结构体转换为 JNA 代码【英文标题】:Translate C struct of function pointers to JNA code 【发布时间】:2017-09-18 04:50:25 【问题描述】:// original c code
struct callback
void (*recv_msg_)(const char * msg, int type, unsigned int len);
void (*connected_)(void *cs);
void (*disconnected_)(void *cs);
;
void recv_msg(const char *msg, int type, unsigned int len)
// some code
//......
void connected(void *s)
// some code
//......
void disconnected(void *s)
// some code
//......
struct callback cb;
cb.recv_msg_ = recv_msg;
cb.connected_ = connected;
cb.disconnected = disconnected;
init("127.0.0.1", 5672, &cb);
// C code end
////////////////////////////////////////////////////////////////////////
// THE JNA code
interface RecvMsg extends Callback
void invoke(String msg, int type, int con_len);
interface CbConnected extends Callback
void invoke(Pointer ctx);
interface CbDisconnected extends Callback
void invoke(Pointer ctx);
class RecvMsgImpl implements RecvMsg
@Override
public void invoke(String msg, int type, int len)
System.out.println("recv msg: " + msg);
class CbConnectedImpl implements CbConnected
@Override
public void invoke(Pointer ctx)
System.out.println("connected.");
class CbDisconnectedImpl implements CbDisconnected
@Override
public void invoke(Pointer ctx)
System.out.println("diconnected.");
public class MyCallBack extends Structure
public RecvMsg recv_msg_;
public CbConnected cb_connected_;
public CbDisconnected cb_disconnected_;
@Override
protected List getFieldOrder()
return Arrays.asList(new String[] "recv_msg_", "cb_connected_", "cb_disconnected_");
MyCallBack cb = new MyCallBack();
cb.recv_msg_ = new RecvMsgImpl();
cb.cb_connected_ = new CbConnectedImpl();
cb.cb_disconnected_ = new CbDisconnectedImpl();
Xxx xxx = (Xxx) Native.loadLibrary("***", Xxx.class);
xxx.init("127.0.0.1", 5672, cb);
// Java code end
////////////////////////////////////////////////////////////////////
我运行java代码,得到如下异常:
Exception in thread "main" java.lang.IllegalArgumentException: Structure field "cb_connected_" was declared as interface DLLTest.CbConnected, which is not supported within a Structure
at com.sun.jna.Structure.writeField(Structure.java:808)
at com.sun.jna.Structure.write(Structure.java:718)
at com.sun.jna.Structure.autoWrite(Structure.java:1923)
at com.sun.jna.Function.convertArgument(Function.java:505)
at com.sun.jna.Function.invoke(Function.java:297)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy1.init(Unknown Source)
at DLLTest.Tester.main(Tester.java:55)
请告诉我如何使用 JNA 将其翻译成 java。
【问题讨论】:
发布你到目前为止所做的事情 java代码是我到目前为止所做的。我得到了异常,但我无法解决它。 【参考方案1】:这是我对 jna 库的测试。
我认为你必须找到与我的不同之处。
我自己编写了代码,因为您没有向我展示完整的源代码。
我的开发环境是一个带有 msys2 的 mingw64 和一个带有 java(1.8) 的 eclipse(oxygen)
这里有更多细节。
Gcc 版本
Using built-in specs.
COLLECT_GCC=C:\DEV\COMP\msys32\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=C:/DEV/COMP/msys32/mingw64/bin/../lib/gcc/x86_64-w64-
mingw32/6.3.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: .....skip
Thread model: posix
gcc version 6.3.0 (Rev1, Built by MSYS2 project)
Java 信息
java.class.version::52.0
sun.management.compiler::HotSpot 64-Bit Tiered Compilers
sun.arch.data.model::64
sun.desktop::windows
sun.cpu.isalist::amd64
首先,你的 JnaTest 类的完整代码。
package ***;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
public class JnaTest
public interface JnaInf extends Library
public void init(String val, int port, MyCallBack cb);
public static void main(String[] args)
MyCallBack cb = new MyCallBack();
cb.recv_msg_ = new RecvMsgImpl();
cb.cb_connected_ = new CbConnectedImpl();
cb.cb_disconnected_ = new CbDisconnectedImpl();
System.load("C:\\DEV\\COMP\\msys32\\home\\***\\jna_inf.dll");
JnaInf xxx = (JnaInf) Native.loadLibrary("jna_inf", JnaInf.class);
xxx.init("127.0.0.1", 5672, cb);
interface RecvMsg extends Callback
void invoke(String msg, int type, int con_len);
interface CbConnected extends Callback
void invoke(Pointer ctx);
interface CbDisconnected extends Callback
void invoke(Pointer ctx);
static class RecvMsgImpl implements RecvMsg
@Override
public void invoke(String msg, int type, int len)
System.out.println("recv msg: " + msg);
System.out.println("type: " + type);
System.out.println("len: " + len);
static class CbConnectedImpl implements CbConnected
@Override
public void invoke(Pointer ctx)
System.out.println("connected.");
static class CbDisconnectedImpl implements CbDisconnected
@Override
public void invoke(Pointer ctx)
System.out.println("diconnected.");
public static class MyCallBack extends Structure
public RecvMsg recv_msg_;
public CbConnected cb_connected_;
public CbDisconnected cb_disconnected_;
@Override
protected List getFieldOrder()
return Arrays.asList(new String[] "recv_msg_", "cb_connected_", "cb_disconnected_" );
那么,c源代码名jna_info.c如下,
struct callback
void (*recv_msg_)(const char * msg, int type, unsigned int len);
void (*connected_)(void *cs);
void (*disconnected_)(void *cs);
;
void recv_msg(const char *msg, int type, unsigned int len)
// some code
//......
void connected(void *s)
// some code
//......
return;
void disconnected(void *s)
// some code
//......
return;
void init(const char *msg, int type, struct callback *mycallback)
mycallback->recv_msg_("123", 22, 3);
mycallback->connected_("123");
return;
编译c源代码
gcc -c jna_inf.c
gcc -shared -o jna_inf.dll jna_inf.o
输出看起来像我所期待的......
我真诚地希望这对你有所帮助。
【讨论】:
以上是关于将函数指针的 C 结构体转换为 JNA 代码的主要内容,如果未能解决你的问题,请参考以下文章
使用 JNA 将本机 C 函数映射到 Java 接口时的指针问题
C 语言结构体 ( 结构体作为函数参数 | 结构体指针作为函数参数 )