P / Invoke e .NET Target Framework [duplicato]

Jan 22 2021

Questo problema mi sta facendo impazzire ... Sto solo dicendo.

La mia azienda dispone di una libreria C ++ legacy e sono stato incaricato di creare un wrapper .NET.
Non ho esperienza di C ++ o P / Invoke, quindi per iniziare sto provando un metodo semplice.

Ho letto la documentazione ufficiale e ho trovato anche un bel tutorial .
Tuttavia, ho scoperto che il framework .NET di destinazione dell'app in uso fa la differenza.
Il codice P / Invoke del tutorial funziona bene ma ho notato che sta prendendo di mira il profilo client .NET Framework 4 .
Se inserisco punti di interruzione, vengono colpiti e tutto funziona come previsto, se scelgo un framework superiore a 4 il programma si arresta in modo anomalo senza eccezioni.

Ho un metodo davvero semplice definito in C ++:
framework.h

extern "C" {
    API char* SayHello();
}

dllmain.cpp

char* SayHello() {
    return (char*)"Hello";
}

C#

        [DllImport("PInvokeTest.dll")]
        public static extern string SayHello();

(Ho provato a impostare CallingConvention e CharSet sull'attributo in diverse combinazioni, sono riuscito a ottenere caratteri cinesi, ma niente funziona più in alto di Framework 4)

Il mio progetto C ++ ha le API=__declspec(dllexport)definizioni del preprocessore impostate e la convenzione di chiamata è _stdcall (\Gz)(ho anche provato _cdecl).
Il progetto C # funziona bene su Framework 4 , quando cambio a qualcosa di cui sopra, quindi esce senza eccezioni.
Ho anche trovato la GUI delle dipendenze che mi mostra che SayHelloè davvero lì.

La nostra azienda utilizza 4.6.1, mi sono anche imbattuto in questo articolo che mi ha portato a PInvokeStackImbalance ma questo non fa nulla nel mio caso.

Qualsiasi aiuto sarebbe molto apprezzato.
Potrei creare un repository GitHub temporaneo, se necessario.

Risposte

LukeTO'Brien Jan 22 2021 at 19:50

Ora che so che si tratta di un problema di stringa, ho fatto una piccola ricerca e ho trovato questa domanda SO .
Quindi alla fine ho usato l' BSTRapproccio.

BSTR SayHello() {
    return ::SysAllocString(L"Hello");
}
        [DllImport("DBReplicator.Lib.dll")]
        [return: MarshalAs(UnmanagedType.BStr)]
        public static extern string SayHello();

... Non so ancora come sono riuscito a ottenere i caratteri cinesi.