Running a JNA example with POSIX message queues

孤街醉人 提交于 2019-12-11 19:05:05

问题


I need to communicate a Java application and a C process via POSIX message queue, and I would like to do it using JNA.

After some research, reading and your help, I started with a simple Java application which tries to create a message queue.

/** Simple example of JNA interface mapping and usage. */
public class HelloJNAWorld {

    // This is the standard, stable way of mapping, which supports extensive
    // customization and mapping of Java to native types.

     public interface IPCLibrary extends Library {
        IPCLibrary INSTANCE = (IPCLibrary)
                Native.loadLibrary("c",IPCLibrary.class);


        int msgget(NativeLong key, int msgflg);

    }

    public static void main(String[] args) {

        int id = IPCLibrary.INSTANCE.msgget(new NativeLong(12500), 0600|1);


        if(id<0){
                System.out.println("Error creating message queue. Id:"+id);
                System.out.println(Native.getLastError());
        }else{
                System.out.println("Message queue id:" + idCola);
        }

    }
}

I thought msgctl was the simplest method to map because it's just int msgget(key_t key, int msgflag);. I have assumed that I could map key_t as a NativeLong but msget is returning -1. So I've checked lastError and the value returned is 2, which means "No such file or directory" according to errno codes.

Could you help me with this? Maybe key_t should be mapped in another way? Maybe I need more libraries or something like that?


回答1:


Since no one answer this question, and some could need the help I needed those days, I'm posting my test class code here. :-)

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.sun.jna.Structure;

/** Simple example of JNA interface mapping and usage. */
public class HelloJNAWorld {

    // This is the standard, stable way of mapping, which supports extensive
    // customization and mapping of Java to native types.

    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)
        Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),CLibrary.class);


        void printf(String format, Object... args);


    }

    public interface IPCLibrary extends Library {
        IPCLibrary INSTANCE = (IPCLibrary)           
        Native.loadLibrary("c",IPCLibrary.class);



        class WaitQueue extends Structure{

        }


        // mapping msqid_ds structure
        class MsqidDs extends Structure{
            long msg_stime;       /* last msgsnd time */
            long msg_rtime;       /* last msgrcv time */
            long msg_ctime;       /* last change time */
            short msg_cbytes;
            short msg_qnum;
            short msg_qbytes;      /* max number of bytes on queue */
            short msg_lspid;       /* pid of last msgsnd */
            short msg_lrpid;       /* last receive pid */
        }

        // END mapping msqid_ds structure

        class MsgBuf extends Structure{
            NativeLong mtype; /* type of message */
            byte mtext[] = new byte[1];
        }


        class MyMsgBuf extends MsgBuf{
            public NativeLong messageKind;
            public byte[] contenido = new byte[1024];
        }

        // Initialize queue, or if it exists, get it            
        int msgget(NativeLong key, int msgflg);
        // Send messages to queue
        // int msgsnd(int msqid, struct msgbuf *ptrkey, int length, int flag);
        int msgsnd(int msqid, MsgBuf ptrkey, int msgsz, int msgflg);
        // Receive messages from queue
        // int msgrcv(int msqid, struct msgbuf *ptrkey, int length, long msgtype, int flag);
        int msgrcv(int msqid, MsgBuf ptrkey, int length, long msgtype, int flag);            

    }

    public static void main(String[] args) {

        int idCola = IPCLibrary.INSTANCE.msgget(new NativeLong(12500), 0);            

        if(idCola<0){
            System.out.println("The queue can't be created. IdCola:"+idCola);           
            System.out.println("Error msgget: " + Native.getLastError());
        }else{
            System.out.println("Queue with id:" + idCola + "has been recovered");           
            // Send message
            IPCLibrary.MyMsgBuf mensaje = new IPCLibrary.MyMsgBuf();
            mensaje.tipoMensaje = new NativeLong(1);
            mensaje.contenido = "Sending message".getBytes();
            int devSend = IPCLibrary.INSTANCE.msgsnd(idCola, mensaje, mensaje.contenido.length, 1);
            if(devSend != 0){
                System.out.println("Send response: "+devSend);
                System.out.println("Error value: " + Native.getLastError());
            }
        }

        // Receiving message
        IPCLibrary.MyMsgBuf mensajeRecibido =  new IPCLibrary.MyMsgBuf();        
        int bytesRecibidos = IPCLibrary.INSTANCE.msgrcv(idCola, mensajeRecibido, mensajeRecibido.contenido.length, 1234, 0);
        if(bytesRecibidos > 0){
            System.out.println("C message has been received: " + new String(mensajeRecibido.contenido));
        }else{
            System.out.println("msgrcv error: " + Native.getLastError());
        }


        // Send closing message
        IPCLibrary.MyMsgBuf mensajeCierre = new IPCLibrary.MyMsgBuf();
        mensajeCierre.tipoMensaje = new NativeLong(2);
        mensajeCierre.contenido = "Closing queue".getBytes();
        int devSend = IPCLibrary.INSTANCE.msgsnd(idCola, mensajeCierre, mensajeCierre.contenido.length, 1);
        if(devSend != 0){
            System.out.println("Send response: "+devSend);
            System.out.println("Error value: " + Native.getLastError());
        }            

    }
}

I really hope this can help someone else.




回答2:


I cleaned up your code and got it running. You need two tasks . one to send and one to receive. just replace the main() in your previous post with the main()'s below. It worked for me. Thanks for posting your efforts for me to start with. Also see kirk.c and spock.c for a good c example http://beej.us/guide/bgipc/output/html/multipage/mq.html

   public static void main(String[] args) {
   double SLEEP_MINUTES = 0.1;
   int IPC_CREAT = 01000;  // starts with 0 so its octal or 512 
   int IPC_EXCL  = 02000;
   int IPC_NOWAIT  = 04000;
   int MSG_EXCEPT = 020000;
   int MSG_NOERROR =  010000;  // truncate the message if its to big     
   int msgflg_msgrcv = MSG_NOERROR; //  truncate the message if its to big
   int msgflg_msgget = 0666 | IPC_CREAT;
   int msgflg_msgsnd = 0;
   int msgtype_msgrcv = 0; // read them all
   NativeLong msgtype_msgsnd = new NativeLong(1); // just needs to be a positive number
   NativeLong msgkey = new NativeLong(12500);  



    int msqid = IPCLibrary.INSTANCE.msgget(msgkey, msgflg_msgget);            

    if(msqid<0)
    {
        System.out.println("The queue can't be created. msqid:"+msqid);           
        System.out.println("Error msgget: " + Native.getLastError());
        System.exit(0);
    }

    System.out.println("Queue with id:" + msqid + "has been found or created");  
    for(int i=0;i<100;i++)
    {
        // Send message
        IPCLibrary.MyMsgBuf message = new IPCLibrary.MyMsgBuf();
        message.messagetype = msgtype_msgsnd;
        message.content = ("Sending message"+i+'\0').getBytes();           // add 1 for the '\0'
        int devSend = IPCLibrary.INSTANCE.msgsnd(msqid, message, message.content.length+1,
                msgflg_msgsnd);
        if(devSend != 0)
        {
            System.out.println("Send response: "+devSend);
            System.out.println("Error value: " + Native.getLastError());
            System.exit(0);
        }
        System.out.println("Sent "+i);            
        try
        {
            Thread.sleep((long)(SLEEP_MINUTES*60.0*1000.0)); 
        }
        catch (InterruptedException e) 
        {
            System.out.println("InterruptedException while writing");
            System.out.println(e.getMessage());                 
        }

    }

}


     public static void main(String[] args) {
// found these in /usr/include/bits/*.h
int IPC_CREAT = 01000;  // remember if it starts with a '0' its octal or 512 
int IPC_EXCL  = 02000;
int IPC_NOWAIT  = 04000;
int MSG_EXCEPT = 020000;
int MSG_NOERROR =  010000;  // truncate the message if its to big     

int msgflg_msgrcv = MSG_NOERROR; //  truncate the message if its to big
int msgflg_msgget = 0666 | IPC_CREAT; // create the queue if its not there , let everybody read and write
int msgtype_msgrcv = 0; // read them all
NativeLong msgtype_msgsnd = new NativeLong(1); // just needs to be a positive number
NativeLong msgkey = new NativeLong(12500);  

    int msqid = IPCLibrary.INSTANCE.msgget(msgkey, msgflg_msgget);            
    if(msqid<0)
    {
        System.out.println("The queue can't be created. msqid:"+msqid);           
        System.out.println("Error msgget: " + Native.getLastError());
        System.exit(0);
    }

    System.out.println("Queue with id:" + msqid + "has been found or was created");  
    for(int i=0;i<100;i++)
    {
        IPCLibrary.MyMsgBuf message =  new IPCLibrary.MyMsgBuf();        
        int ret = IPCLibrary.INSTANCE.msgrcv(msqid, message, message.content.length,
                msgtype_msgrcv,msgflg_msgrcv);
        if(ret > 0)
        {
            System.out.println("message has been received: " + ret);
            System.out.println(new String(message.content));
        }
        else
        {
            System.out.println("msgrcv error: " + Native.getLastError());
        }
    }

   }
 }


来源:https://stackoverflow.com/questions/11879101/running-a-jna-example-with-posix-message-queues

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!