java - 将函数指针的 C 结构体转换为 JNA 代码

标签 java c++ c

// 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。

最佳答案

这是我使用 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 stackoverflow;

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\\stackoverflow\\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

输出看起来像我所期望的..

enter image description here

我真诚地希望这对您有帮助。

关于java - 将函数指针的 C 结构体转换为 JNA 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46271802/

相关文章:

java - 如何以编程方式使图像适合 ImageButton

java - 如何更改不同类的主方法中的值

c - 我如何从二维数组中获取每列的总和并将其保存到 C 中的一维数组

C: Eclipse/gdb 和空终止字符串

java - 为什么 TRANSACTION_READ_COMMITTED 是 Java 中的默认值?

java - 如何使用 SpEL 处理 Thymeleaf 中的本地化消息

c++ - 我无法在类中获取 MBED 代码来调用成员方法

c++ - 重新排列二维数组

c++ - 如何使用 C++ 在 LUA 中编写具有对话和菜单的交互式 NPC 脚本?

c++ - GLUTesselator 的替代品?