Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I map the following elements of a C Structure to Java?

I have the following C Structure which needs to be mapped to Java. Because I need to call a method from a DLL generated from the C code. The following is my structure.

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;

The IPJ_READER_CONTEXT and IPJ_READER_IDENTIFIER looks like below.

typedef void* IPJ_READER_CONTEXT;
typedef void* IPJ_READER_IDENTIFIER;

How can I parse those two elements to map to Java? Please advice.

like image 911
AnOldSoul Avatar asked Nov 27 '22 05:11

AnOldSoul


1 Answers

You can use JNIWrapper to map your C structure to Java and call the function from DLL.

The wrapper for the given structure will look like shown below (the values for the size constants need to be changed):

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;
    }
}

If you need a pointer to the structure instance, you should create the Pointer class instance:

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

After that, you can use the pointer instance to pass the function parameter. The following code demonstrates how to load the library and call the function from it:

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

If the structure is modified after the call, all the changes will be available in the structureInstance object.

As you can see, in this case you do not need to write any additional native code.

You can find more details about using JNIWrapper in its programmer's guide. Also, there is the JNIWrapper forum that contains answers to many popular questions.

like image 198
Anna Dolbina Avatar answered Dec 29 '22 10:12

Anna Dolbina