如何将C结构的以下元素映射到Java?

时间:2015-11-06 07:38:09

标签: java c java-native-interface jniwrapper

我有以下需要映射到Java的C结构。因为我需要从C代码生成的DLL中调用一个方法。以下是我的结构。

typedef struct _ipj_iri_device
{
IPJ_READER_CONTEXT    reader_context;
IPJ_READER_IDENTIFIER reader_identifier;
uint32_t              receive_timeout_ms;

/* Internal Only */
uint8_t               sync_state;
bool                  wait_for_response;
uint32_t              frame_length;
uint32_t              receive_index;
uint8_t               receive_buffer[IPJ_RECEIVE_BUFFER_SIZE];

#if !defined(IRI_RX_ONLY)
uint8_t               transmit_buffer[IPJ_TRANSMIT_BUFFER_SIZE];
#endif

} ipj_iri_device;

IPJ_READER_CONTEXT和IPJ_READER_IDENTIFIER如下所示。

typedef void* IPJ_READER_CONTEXT;
typedef void* IPJ_READER_IDENTIFIER;

如何解析这两个元素以映射到Java?请指教。

3 个答案:

答案 0 :(得分:0)

以下是使用JNA显示结构的示例:

public class ipj_iri_device extends Structure {
    Pointer               reader_context;
    Pointer               reader_identifier;
    int                   receive_timeout_ms;
    /* Internal Only */
    byte                  sync_state;
    // field size depends on size of 'bool'; "byte" is usually correct
    byte                  wait_for_response; 
    int                   frame_length;
    int                   receive_index;
    byte[]                receive_buffer = new byte[IPJ_RECEIVE_BUFFER_SIZE];
    // may or may not be used, check your native compile flag
    byte[]                transmit_buffer = new byte[IPJ_TRANSMIT_BUFFER_SIZE];
}

如果您需要其内容,可以定义支持reader_contextreader_identifier字段的结构。如果没有,您可以将它们作为通用Pointer传递。

修改

这些结构可以独立于JNA的其余部分使用,您只需要本地内存的Pointer表示来来回移动数据。

答案 1 :(得分:0)

您可以使用JNIWrapper将C结构映射到Java并从DLL调用该函数。

给定结构的包装器如下所示(需要更改大小常量的值):

import com.jniwrapper.*;

public class IpjIriDevice extends Structure
{
    private static final int IPJ_RECEIVE_BUFFER_SIZE = 0;
    private static final int IPJ_TRANSMIT_BUFFER_SIZE = 0;

    private Pointer.Void reader_context = new Pointer.Void();
    private Pointer.Void reader_identifier = new Pointer.Void();
    private UInt32 receive_timeout_ms = new UInt32();
    private UInt8 sync_state = new UInt8();
    private Bool wait_for_response = new Bool();
    private UInt32 frame_length = new UInt32();
    private UInt32 receive_index = new UInt32();
    private PrimitiveArray receive_buffer = new PrimitiveArray(UInt8.class, IPJ_RECEIVE_BUFFER_SIZE);
    private PrimitiveArray transmit_buffer = new PrimitiveArray(UInt8.class, IPJ_TRANSMIT_BUFFER_SIZE);

    public IpjIriDevice()
    {
        init(new Parameter[] {
            reader_context,  
            reader_identifier,  
            receive_timeout_ms,  
            sync_state,  
            wait_for_response,  
            frame_length,  
            receive_index,  
            receive_buffer,  
            transmit_buffer
        });
    }

    public long getReaderContext()
    {
        return reader_context.getValue();
    }

    public long getReaderIdentifier()
    {
        return reader_identifier.getValue();
    }

    public long getReceiveTimeoutMs()
    {
        return receive_timeout_ms.getValue();
    }

    public void setReceiveTimeoutMs(long value)
    {
        receive_timeout_ms.setValue(value);
    }

    public long getSyncState()
    {
        return sync_state.getValue();
    }

    public void setSyncState(long value)
    {
        sync_state.setValue(value);
    }

    public boolean getWaitForResponse()
    {
        return wait_for_response.getValue();
    }

    public void setWaitForResponse(boolean value)
    {
        wait_for_response.setValue(value);
    }

    public long getFrameLength()
    {
        return frame_length.getValue();
    }

    public void setFrameLength(long value)
    {
        frame_length.setValue(value);
    }

    public long getReceiveIndex()
    {
        return receive_index.getValue();
    }

    public void setReceiveIndex(long value)
    {
        receive_index.setValue(value);
    }

    public PrimitiveArray getReceiveBuffer()
    {
        return receive_buffer;
    }

    public PrimitiveArray getTransmitBuffer()
    {
        return transmit_buffer;
    }

    public Object clone()
    {
        IpjIriDevice result = new IpjIriDevice();
        result.initFrom(this);
        return result;
    }
}

如果需要指向结构实例的指针,则应创建Pointer类实例:

IpjIriDevice structureInstance = new IpjIriDevice();
Pointer structurePtr = new Pointer(structureInstance);

之后,您可以使用指针实例传递函数参数。以下代码演示了如何加载库并从中调用函数:

DefaultLibraryLoader.getInstance().addPath(LIB_PATH);
Library library = new Library(LIB_NAME);
Function function = library.getFunction(FUNCTION_NAME);
long errorCode = function.invoke(returnValue, structurePtr);

如果在调用后修改了结构,则所有更改都将在structureInstance对象中可用。

如您所见,在这种情况下,您无需编写任何其他本机代码。

您可以在programmer's guide中找到有关使用JNIWrapper的更多详细信息。此外,还有JNIWrapper forum包含许多热门问题的答案。

答案 2 :(得分:-1)

Aah经过长时间的搜索,在这里找到了一个关于OOP vs的感兴趣的人      功能范式。      所以在这里我们可以解决它。      这是基本步骤。

  • 将您的结构命名为一个类。
  • 将结构的所有属性作为类属性。

  • 对于那些void *,在java中你可以使用引用变量。

  • 然后对于一个结构实例,因为你得到了ipj_iri_device名称的结构,只需创建一个以bullet a命名的类的对象。

    public class _ipj_iri_device{
         int IPJ_RECEIVE_BUFFER_SIZE ;
         //get a value from whereever the input is coming ,assign it to buffersize
         IPJ_READER_CONTEXT    reader_context;
         IPJ_READER_IDENTIFIER reader_identifier;
         boolean wait_for_response;
         uint32_t receive_timeout_ms;
         //here uint32_t is a type  i asumed .You will have to define it explicitly
    
        //rest of the vaariables / members of structure 
     }