P / Invoke i .NET Target Framework [duplikat]

Jan 22 2021

Ta kwestia doprowadza mnie do góry nogami ... Tylko mówię.

Moja firma ma starszą bibliotekę C ++ i otrzymałem zadanie stworzenia opakowania .NET.
Nie mam doświadczenia w C ++ ani P / Invoke, więc na początek próbuję prostej metody.

Przeczytałem oficjalną dokumentację i znalazłem też fajny tutorial .
Jednak odkryłem, że docelowy framework .NET używanej aplikacji robi różnicę.
Kod P / Invoke z samouczka działa dobrze, ale zauważyłem, że jego celem jest .NET Framework 4 Client Profile .
Jeśli umieszczę punkty przerwania, zostaną one trafione i wszystko działa zgodnie z oczekiwaniami, jeśli celuję w strukturę wyższą niż 4, program zawiesza się bez wyjątku.

Mam naprawdę prostą metodę zdefiniowaną w C ++:
framework.h

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

dllmain.cpp

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

C#

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

(Próbowałem ustawić CallingConvention i CharSet na atrybucie w różnych kombinacjach, udało mi się uzyskać chińskie znaki, ale nic nie działa wyżej niż Framework 4)

Mój projekt w C ++ ma API=__declspec(dllexport)ustawione definicje preprocesora i konwencję _stdcall (\Gz)wywoływania (próbowałem też _cdecl).
Projekt C # działa dobrze na Framework 4 , kiedy zmieniam na coś powyżej, to po prostu kończy się bez wyjątku.
Znalazłem również GUI zależności, które pokazuje mi, że SayHellorzeczywiście tam jest.

Nasza firma używa 4.6.1, natknąłem się również na ten artykuł, który doprowadził mnie do PInvokeStackImbalance, ale to nic nie robi w moim przypadku.

Każda pomoc byłaby bardzo mile widziana.
W razie potrzeby mógłbym utworzyć tymczasowe repozytorium GitHub.

Odpowiedzi

LukeTO'Brien Jan 22 2021 at 19:50

Teraz, gdy wiem, że jest to problem ze stringami, poszukałem trochę i znalazłem to pytanie SO .
Więc w końcu zastosowałem to BSTRpodejście.

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

... Nadal nie wiem, jak udało mi się uzyskać chińskie znaki.