P / Invoke и .NET Target Framework [дубликат]

Jan 22 2021

Эта проблема сводит меня с ума ... Просто говорю.

В моей компании есть устаревшая библиотека C ++, и мне было поручено создать оболочку .NET.
У меня нет опыта работы с C ++ или P / Invoke, поэтому для начала я пробую простой метод.

Я прочитал официальную документацию, а также нашел хорошее руководство .
Однако я обнаружил, что целевая платформа .NET потребляющего приложения имеет значение.
Код P / Invoke из учебника работает нормально, но я заметил, что он нацелен на профиль клиента .NET Framework 4 .
Если я размещаю точки останова, они срабатывают, и все работает, как ожидалось, если я нацелен на фреймворк выше 4, программа вылетает без исключения.

У меня есть действительно простой метод, определенный на C ++:
framework.h

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

dllmain.cpp

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

C#

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

(Я попытался установить CallingConvention и CharSet для атрибута в разных комбинациях, мне удалось получить китайские символы, но ничего не работает выше Framework 4)

В моем проекте на C ++ есть API=__declspec(dllexport)набор определений препроцессора и соглашение _stdcall (\Gz)о вызовах (я также пробовал _cdecl).
Проект C # отлично работает в Framework 4 , когда я меняю на что-то выше, он просто завершается без исключения.
Я также нашел графический интерфейс зависимостей, который показывает мне, что SayHelloдействительно существует.

Наша компания использует 4.6.1, я также наткнулся на эту статью, которая привела меня к PInvokeStackImbalance, но в моем случае это ничего не дает.

Любая помощь будет принята с благодарностью.
При необходимости я мог бы создать временное репозиторий GitHub.

Ответы

LukeTO'Brien Jan 22 2021 at 19:50

Теперь, когда я знаю, что это проблема со строкой, я немного поискал и нашел этот вопрос SO .
В конце концов, я применил свой BSTRподход.

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

... До сих пор не знаю, как мне удалось получить китайские иероглифы.