Вопрос

Я новичок в теме импорта C ++ dll, и, возможно, мой вопрос очень прост, но я не могу найти его в Google.

У меня есть очень простая библиотека C ++ win32 dll:

#include <iostream>

using namespace std;

extern "C"
{
    __declspec(dllexport) void __stdcall DisplayHellowFromDLL()
    {
        cout<<"Hi"<<endl;
    }
}

Когда я вызываю этот метод из C #, у меня не возникает никаких проблем, вот C # код

namespace UnmanagedTester
{
    class Program
    {
        [DllImport(@"C:\CGlobalDll")]
        public static extern void DisplayHellowFromDLL();

        static void Main(string[] args)
            {
                Console.WriteLine("This is C# program");
                DisplayHellowFromDLL();
            }
        }
    }

Как я и ожидал, результат таков:"Это программа на C #" - "Привет".

Теперь, если я изменю объявление функции C следующим образом:

__declspec(dllexport) void DisplayHellowFromDLL()

без __stdcall у меня также нет никаких проблем, и вопрос в следующем:

Когда мне действительно нужен __declspec(dllexport) ВВЕДИТЕ __stdcall, а когда я могу использовать только __declspec(dllexport) ВВЕДИТЕ?

Большое спасибо.

Это было полезно?

Решение

Вам необходимо указать Конвенцию о вызове, если вы составите вызовный код с некоторым другим соглашением. В противном случае по умолчанию будет работать.

Другие советы

Вы можете думать об этом так:

  1. __declspec(dllexport) объявляет вашу функцию публичной функцией, что ваш DLL экспортирует;

  2. __stdcall это довольно низкоуровневая деталь, которая относится к «конвенции о вызове», принятой этой функцией; конкретно, __stdcall означает, что Callee очищает стек;

  3. Альтернативой __stdcall является __cdecl, что означает: звонящий очищает стек.

__cdecl это «естественное» C -вызововое соглашение; Он поддерживает определение функций Vararg (например, printf).

__stdcall Является ли соглашение о вызове по умолчанию для функций DLL, поэтому вам не нужно указывать его, если вы собираетесь вызовать эти функции через их API DLL.

Это должно объяснить, что вы наблюдаете.

Это работает случайно, потому что функция не принимает никаких аргументов. Как только вы сделаете это на функции, которая делает Возьмите аргументы, которые у вас начнется удача. Звонок оставит стек несбалансированным, очень нездоровым. Вы получите Pinvokestackimbalance MDA Предупреждение Когда вы отлаживаете. В противном случае несбалансированная стека может некоторое время остаться незамеченным, он имеет тенденцию к сбою вашей программы в сборке релиза.

Илья, вы также можете установить соглашение о вызовах по умолчанию в свойствах проекта -> Свойства конфигурации -> C / C ++ -> Дополнительно -> Соглашение о вызовах.Если соглашение о вызовах по умолчанию в вашем проекте уже установлено в __stdcall (/Gz), то добавьте __std

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top