declspec и stdcall против только declspec
Я новый человек для C++ dll импорта темы и может быть мой вопрос очень легко, но я не могу найти его на google.
у меня очень простая dll win32 c++:
#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) TYPE __stdcall и когда я могу использовать только _ _ declspec(dllexport) TYPE ?
Спасибо большое.
4 ответов
вам нужно указать соглашение о вызове, если вы компилируете код вызова с каким-либо другим соглашением. В противном случае будет работать значение по умолчанию.
вы можете думать об этом так:
__declspec(dllexport)
объявляет вашу функцию общедоступной функцией, которую экспортирует ваша DLL;__stdcall
- довольно низкоуровневая деталь, которая ссылается на" соглашение о вызовах", принятое этой функцией; в частности,__stdcall
означает, что вызываемый очищает стек;альтернатива
__stdcall
is__cdecl
, что означает: вызывающий очищает стек.
__cdecl
является" естественным " соглашением о вызове C; он поддерживает определение функций vararg (например, printf).
__stdcall
является соглашением о вызове по умолчанию для функций DLL, поэтому вам не нужно указывать его, если вы собираетесь вызывать эти функции только через их API DLL.
это должно объяснить, что вы наблюдаете.
Он работает случайно, потому что функция не принимает никаких аргументов. Как только вы это сделаете на функции, которая тут принимать аргументы запуска повезло. Вызов оставит стек несбалансированным, очень нездоровым. Ты pInvokeStackImbalance MDA предупреждение при отладке. Несбалансированный стек может остаться незамеченным на некоторое время, он имеет тенденцию к сбою вашей программы в сборке выпуска.
Илья, вы также можете установить соглашение о вызовах по умолчанию в свойствах проекта - > свойства конфигурации - > C / C++ - > дополнительно - > соглашение о вызовах. Если соглашение о вызовах по умолчанию в вашем проекте уже установлено в __stdcall (/Gz), то добавление __std