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?
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.