Java 带指针的C结构,如何Swig?

Java 带指针的C结构,如何Swig?,java,c,pointers,swig,Java,C,Pointers,Swig,我正试图使用Swig为一些内部C代码生成包装器,这样我就可以在新的androidjava项目中重用它,但我遇到了一些问题。我对Java和Swig都是新手,所以请在任何回复的技术内容方面对我温和一些 我试图包装一个名为S_MESSAGE_STRUCT的C结构,它包含指针,这样它的元素就可以从java和遗留C代码访问(设置、编写、读取等)。我的定义结构的C头文件如下所示,代码是示例性的,并且与我的实际代码(具有相同的问题)相比得到了简化: 我正在使用.I文件,如下所示: #include "mess

我正试图使用Swig为一些内部C代码生成包装器,这样我就可以在新的androidjava项目中重用它,但我遇到了一些问题。我对Java和Swig都是新手,所以请在任何回复的技术内容方面对我温和一些

我试图包装一个名为S_MESSAGE_STRUCT的C结构,它包含指针,这样它的元素就可以从java和遗留C代码访问(设置、编写、读取等)。我的定义结构的C头文件如下所示,代码是示例性的,并且与我的实际代码(具有相同的问题)相比得到了简化:

我正在使用.I文件,如下所示:

#include "message.h"

bool t_func(P_S_MESSAGE_STRUCT p_s_mystruct)
{
    if (*p_s_mystruct->i1 == 1)
    {
        strcpy(p_s_mystruct->c1, "Hello from swig");
        p_s_mystruct->c1[p_s_mystruct->len-1] = '\0';
        *p_s_mystruct->i1 = strlen(p_s_mystruct->c1);
    }

    return true;
}
/* File : Message.i */
%module Message
%{
/* Includes the header in the wrapper code */
#include "../../../common/message/message.h"
%}

// Enable the JNI class to load the required native library.
%pragma(java) jniclasscode=%{
 static {
 try {
 java.lang.System.loadLibrary("Message");
 } catch (UnsatisfiedLinkError e) {
 java.lang.System.err.println("native code library failed to load.\n" + e);
 java.lang.System.exit(1);
 }
 }
%}

%include <typemaps.i>
%apply signed char * INOUT {char*};

typedef struct
{
    int*      i1;
    char*   c1;
    int       len;
} *P_S_MESSAGE_STRUCT, S_MESSAGE_STRUCT;

%include cpointer.i

bool t_func(P_S_MESSAGE_STRUCT p_s_mystruct);

%pointer_functions(int, intp);
但是我知道我做错了什么,因为在我从java调用t_func()函数之后,我不断遇到一些问题。问题是多方面的,包括对t_func()的调用完成后程序挂起,但有时程序运行并显示输出OK。当显示输出时,c1的贡献为空(它只给出输出“15”,没有“来自swig的你好”的符号)

我已经确定程序片状是由对p_MYSTRUCT结构中指针元素i1和c1的写入引起的,因为没有这些元素或没有写入(但将c1、i1元素保留在结构中)都没有问题

如果您能帮助我实现使用C结构的指针元素的目标,并了解我在邮件中的错误,我将不胜感激。I文件?我使用的是SWIG版本3.0.2。 谢谢

迈克

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!编辑:

我发现,如果我更改消息中的以下行,我

%apply signed char * INOUT {char*};

我的Swig调用产生以下错误:

Warning 453: Can't apply (byte *INOUT). No typemaps are defined.
但是,生成的代码编译并运行正常,附带条件是我需要更改java应用程序代码,以便在其c1版本中使用字符串而不是字节[]

我的新java代码是:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

/*  typedef struct
    {
            int* i1;
            char* c1;
            int len;
    }*P_MYSTRUCT, MYSTRUCT;*/
    S_MESSAGE_STRUCT p_my_struct = new S_MESSAGE_STRUCT();

    int i1 = 1;
    SWIGTYPE_p_int i1p = Message.new_intp();
    Message.intp_assign(i1p, i1);

    int len = 128;
    byte[] c1 = new byte[len];

    String s1 = new String(c1);
    p_my_struct.setI1(i1p);
    p_my_struct.setC1(s1);
    p_my_struct.setLen(len);

    Message.t_func(p_my_struct);

    SWIGTYPE_p_int pi1_ret = p_my_struct.getI1();
    Integer i1_ret = Message.intp_value(pi1_ret);
    String display = p_my_struct.getC1();

    display += i1_ret;

    final EditText eText = (EditText) findViewById(R.id.editText1);

    eText.setText(display);
}
这能说明我可能做错了什么吗

收到的任何想法

Mike

我们也可以使用,这比作为作者的SWIG更容易使用

使用此配置类:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
import org.bytedeco.javacpp.tools.*;

@Properties(value=@Platform(include="message.h", link="theMessageLibFile"), target="Message")
public class MessageConfig implements InfoMapper {
    public void map(InfoMap infoMap) {
        infoMap.put(new Info("P_S_MESSAGE_STRUCT").valueTypes("S_MESSAGE_STRUCT"));
    }
}
通过执行

$ javac -cp javacpp.jar MessageConfig.java
$ java -jar javacpp.jar MessageConfig
解析器生成此包装器类:

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

public class Message extends MessageConfig {
    static { Loader.load(); }

public static class S_MESSAGE_STRUCT extends Pointer {
    static { Loader.load(); }
    public S_MESSAGE_STRUCT() { allocate(); }
    public S_MESSAGE_STRUCT(int size) { allocateArray(size); }
    public S_MESSAGE_STRUCT(Pointer p) { super(p); }
    private native void allocate();
    private native void allocateArray(int size);
    @Override public S_MESSAGE_STRUCT position(int position) {
        return (S_MESSAGE_STRUCT)super.position(position);
    }

    public native IntPointer i1(); public native S_MESSAGE_STRUCT i1(IntPointer i1);
    public native @Cast("char*") BytePointer c1(); public native S_MESSAGE_STRUCT c1(BytePointer c1);
    public native int len(); public native S_MESSAGE_STRUCT len(int len);
}

public static native @Cast("bool") boolean t_func(S_MESSAGE_STRUCT p_s_mystruct);
}
然后,我们可以通过调用以下命令来构建本机库:

$ javac -cp javacpp.jar Message.java
$ java -jar javacpp.jar Message
其工作原理与预期一致,例如:

import org.bytedeco.javacpp.*;

public class Main {
    public static void main(String[] args) {
        Message.S_MESSAGE_STRUCT my_struct = new Message.S_MESSAGE_STRUCT();
        IntPointer i1 = new IntPointer(1).put(1);
        BytePointer c1 = new BytePointer(128);
        my_struct.i1(i1);
        my_struct.c1(c1);
        my_struct.len(c1.capacity());
        Message.t_func(my_struct);
        System.out.println(c1.getString());
    }
}
产出如下:

Hello from JavaCPP

我看不到指针
i1
c1
在哪里被分配了内存位置的地址。我看到您在哪里使用
setI1()
setC1()
并使用
setC1()将Java句柄传递给Java数组
但是,我不希望Java内存句柄与C指针地址相同。此SWIG页也可以提供帮助。请同时查看和。@RC:int i1=1;SWIGTYPE_p_int i1p=Message.new_intp();Message.intp_assign(i1p,i1);@RC:代码中定义和初始化整数的位置是以下行中的第一行:int i1=1;SWIGTYPE_p_int i1p=Message.new_intp();Message.intp_assign(i1p,i1);SWIGTYPE_p_int是指向int的指针,在第2行中创建,int在第三行中分配给该指针。结构的i1元素稍后在代码中通过以下行分配给指针:p_my_struct.setI1(i1p);如您所述。
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

public class Message extends MessageConfig {
    static { Loader.load(); }

public static class S_MESSAGE_STRUCT extends Pointer {
    static { Loader.load(); }
    public S_MESSAGE_STRUCT() { allocate(); }
    public S_MESSAGE_STRUCT(int size) { allocateArray(size); }
    public S_MESSAGE_STRUCT(Pointer p) { super(p); }
    private native void allocate();
    private native void allocateArray(int size);
    @Override public S_MESSAGE_STRUCT position(int position) {
        return (S_MESSAGE_STRUCT)super.position(position);
    }

    public native IntPointer i1(); public native S_MESSAGE_STRUCT i1(IntPointer i1);
    public native @Cast("char*") BytePointer c1(); public native S_MESSAGE_STRUCT c1(BytePointer c1);
    public native int len(); public native S_MESSAGE_STRUCT len(int len);
}

public static native @Cast("bool") boolean t_func(S_MESSAGE_STRUCT p_s_mystruct);
}
$ javac -cp javacpp.jar Message.java
$ java -jar javacpp.jar Message
import org.bytedeco.javacpp.*;

public class Main {
    public static void main(String[] args) {
        Message.S_MESSAGE_STRUCT my_struct = new Message.S_MESSAGE_STRUCT();
        IntPointer i1 = new IntPointer(1).put(1);
        BytePointer c1 = new BytePointer(128);
        my_struct.i1(i1);
        my_struct.c1(c1);
        my_struct.len(c1.capacity());
        Message.t_func(my_struct);
        System.out.println(c1.getString());
    }
}
Hello from JavaCPP