2013-03-14 3 views
15

Mein Ziel ist es, Daten von einem C++ - Prozess zu einem Java-Prozess zu übergeben und dann ein Ergebnis zurück zu erhalten.Gemeinsamer Speicher zwischen C++ - und Java-Prozessen

Ich habe dies über eine Named Pipe erreicht, aber ich würde lieber die Daten teilen als sie zu übergeben oder zu kopieren, vorausgesetzt, der Zugriff wäre schneller.

Anfangs dachte ich daran, ein gemeinsames Segment in C++ zu erstellen, mit dem ich schreiben und mit Java lesen könnte, aber ich bin mir nicht sicher, ob dies über JNI möglich ist, geschweige denn sicher.

Ich glaube, es ist in Java möglich, den Speicher mit ByteBuffer.allocateDirect zuzuweisen und dann GetDirectBufferAddress verwenden, um auf die Adresse in C++ zuzugreifen, aber wenn ich richtig bin, ist dies für native Anrufe innerhalb JNI und ich kann diese Adresse nicht erhalten in meinem C++ Prozess?

Verloren.

Vielen Dank im Voraus.

Antwort

4

Haben Sie in Betracht gezogen, 0MQ zu verwenden, unterstützt es sowohl Java als auch C++ und wird zuverlässiger sein. Ich denke, wenn Sie Shared Memory in Java machen wollen, müsste es über JNI sein, das letzte Mal, als ich nachgesehen habe, gab es keinen anderen Weg, es zu tun.

Dies zeigt, dass Sie es über JNI tun müssen, wenn Sie diese Route gehen. Obwohl die Lösungen, die ich gefunden habe, sind Windows-spezifische, die möglicherweise nicht für Sie gelten.

13

Wenn Sie Speicher teilen, zum Beispiel CreateFileMapping (Windows) oder shmget (Unix), alles was Sie brauchen, ist eine native Methode auf der Java-Seite. Dann können Sie eine erstellen ByteBuffer dass direkt greift auf den gemeinsam genutzten Speicher NewDirectByteBuffer wie folgt aus:

JNIEXPORT jobject JNICALL Java_getSharedBuffer(JNIEnv* env, jobject caller) { 
    void* myBuffer; 
    int bufferLength; 

Jetzt müssen Sie einen Zeiger auf den gemeinsam genutzten Speicher erhalten. Unter Windows würden Sie so etwas wie folgt verwenden:

bufferLength = 1024; // assuming your buffer is 1024 bytes big 
    HANDLE mem = OpenFileMapping(FILE_MAP_READ, // assuming you only want to read 
      false, "MyBuffer"); // assuming your file mapping is called "MyBuffer" 
    myBuffer = MapViewOfFile(mem, FILE_MAP_READ, 0, 0, 0); 
    // don't forget to do UnmapViewOfFile when you're finished 

Jetzt können Sie nur eine ByteBuffer erstellen, die von diesem gemeinsam genutzten Speicher gesichert wird:

// put it into a ByteBuffer so the java code can use it 
    return env->NewDirectByteBuffer(myBuffer, bufferLength); 
}