Das Verhalten von extern "C"



  • Hallo,

    ich habe gerade mehrere Stunden daran gesessen, den MinGW g++ compiler C-kompatible Symbole erzeugen zu lassen.

    Das C++ Mangling Verhalten gewöhnt man ja dem Compiler mit extern "C" ab. Der MinGW zeigt da einen für meinen Geschmack etwas seltsames Verhalten:

    Ich habe mit Java´s JNI gebastelt, und da ist das ja so, dass einem die C Header autogeneriert werden.

    Java erzeugt mit so etwas, wichtig ist hier eigentlich nur dass "extern".

    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     Renderer_RenderDevice
     * Method:    createDisplay
     * Signature: (IIZ)V
     */
    JNIEXPORT void JNICALL Java_Renderer_RenderDevice_createDisplay
      (JNIEnv *, jclass, jint, jint, jboolean);
    
    /*
     * Class:     Renderer_RenderDevice
     * Method:    setTitle
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_Renderer_RenderDevice_setTitle
      (JNIEnv *, jclass, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    

    Wenn ich nun auf diese Weise eine Implementierung angebe, erzeugt der MinGW trotzdem falsche Symbole. (Immer noch C++)

    JNIEXPORT void JNICALL Java_Renderer_RenderDevice_createDisplay
                (JNIEnv* env, jobject o, jint width, jint height, jboolean fullscreen) {
    
            std::cout << "Wahoo: " << width << "," << height << std::endl;
    
        }
    

    Ich fand es dann auch recht logisch export "C" den Funktionsdefinitionen voranzustellen - hier kommt es ja schliesslich drauf an, nur gab es dann die Fehlermeldung:

    RenderDevice.cc:14: error: declaration of C function `void Java_Renderer_RenderDevice_createDisplay(JNIEnv*, _jobject*, jint, jint, jboolean)' conflicts with
    
    ../RenderDevice.h:16: error: previous declaration `void Java_Renderer_RenderDevice_createDisplay(JNIEnv*, _jclass*, jint, jint, jboolean)' here
    

    Angeblich sind die Deklarationen verschieden... es sind aber beide mit extern "C" definiert - also gleich.

    Wenn ich nun das extern "C" aus den headern streiche, klappt alles korrekt.
    Also alles kein Problem - es läuft, nur
    1.) Verstehe ich das nicht
    2.) Muss ich jedesmal das extern "C" streichen, wenn die header neu generiert werden ? Es wäre ja seltsam, wenn Suns header generell nicht funktionieren würde.

    Ist das ein Nichtstandart-Verhalten von MinGW ? Oder gibt es eine Lösung ohne die Header zu verändern ?

    Ich hoffe jemand von euch kann da etwas Licht reinbringen,
    Danke!!!
    Frederick



  • kann es sein das die typen

    RenderDevice.cc:14: error: declaration of C function `void Java_Renderer_RenderDevice_createDisplay(JNIEnv*, _jobject*, jint, jint, jboolean)' conflicts with

    ../RenderDevice.h:16: error: previous declaration `void Java_Renderer_RenderDevice_createDisplay(JNIEnv*, _jclass*, jint, jint, jboolean)' here

    unteschiedlich sind?



  • hab letzt mit mingw ne jni lib bauen wollen und trotz linker options wie --kill-at konnt ich ihn nicht dazu bewegen, die symbole rauszukicken. hab mir dann beholfen, indem ich JNICALL rausgeschmissen hab und __declspec(dllexport) verwendete.

    achso, und ja, die beiden methoden werden dieselbe signatur haben, wenn du die dekorationen streichst. vielleicht ists in deinem fall dann besser, nen mapping zu verwenden.



  • kann es sein das die typen
    ...
    unteschiedlich sind?

    😮 Oh nein - wie dämlich 🙄
    Booar es war einfach zu spät gestern nacht. - Läuft jetzt alles prima.
    Keine Ahnung wie der Fehler da reingerutscht ist... ich hab ja Cut`n´Paste
    aus dem Header gemacht.

    hab letzt mit mingw ne jni lib bauen wollen und trotz linker options wie --kill-at konnt ich ihn nicht dazu bewegen, die symbole rauszukicken

    Das einzige was --kill-at macht ist ein @n von den Symbolen zu entfernen, wobei
    n eine Zahl ist, die angibt wieviel Speicher die Funktion auf dem Stack benötigt, das ist aber nur ein Schritt, das C++mangling bekommst dadurch nicht weg. Schau dir mal http://wyw.dcweb.cn/stdcall.htm dazu an, das hat mir ganz gut geholfen.
    Bei mir hat es --add-stdcall-alias getan, aber das hast du ja wahrscheinlich auch probiert. Das Mangling verschwindet nur, wenn man die Funktionsdefinitionen in einen extern "C" Block packt. Ist vielleicht das gleiche wie __declspec(dllexport). Probier mal aus - bei mir klappt das so.
    Achja und ich verwende noch -D_JNI_IMPLEMENTATION. Hab aber keine Ahnung was das tut.

    Jippey - jetzt klappt endlich alles.


Anmelden zum Antworten