__declspec e stdcall ou __declspec apenas
Pergunta
Sou uma nova pessoa no tópico de importação de dll C ++ e minha dúvida é muito fácil, mas não consigo encontrar no google.
Eu tenho uma dll C ++ win32 muito simples:
#include <iostream>
using namespace std;
extern "C"
{
__declspec(dllexport) void __stdcall DisplayHellowFromDLL()
{
cout<<"Hi"<<endl;
}
}
Quando eu chamo esse método em C #, não tenho nenhum problema, aqui está o código 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();
}
}
}
Como eu esperava, o resultado é: "Este é um programa C #" "Olá".
Agora, se eu alterar a declaração da função C como:
__declspec(dllexport) void DisplayHellowFromDLL()
sem __stdcall, não tenho nenhum problema também, e a pergunta é:
Quando eu realmente preciso de __declspec (dllexport) TYPE __stdcall e quando posso usar apenas __declspec (dllexport) TYPE?
Muito obrigado.
Solução
Você precisa especificar a convenção de chamada se compilar o código de chamada com alguma outra convenção.Caso contrário, o padrão funcionará.
Outras dicas
Você pode pensar assim:
-
__declspec(dllexport)
declara sua função como uma função pública que sua DLL exporta; -
__stdcall
é um detalhe de baixo nível que se refere à "convenção de chamada" adotada por aquela função;especificamente,__stdcall
significa que o receptor limpa a pilha; -
alternativa para
__stdcall
é__cdecl
, o que significa: o chamador limpa a pilha.
__cdecl
é a convenção de chamada C "natural";ele suporta a definição de funções vararg (como printf).
__stdcall
é a convenção de chamada padrão para funções DLL, portanto, você não precisa especificá-la se for apenas chamar essas funções por meio da API DLL.
Isso deve explicar o que você está observando.
Funciona por acidente porque a função não aceita argumentos.Assim que você fizer isso em uma função que aceita argumentos, você começará a ficar sem sorte.A chamada deixará a pilha desequilibrada, muito insalubre.Você receberá o aviso de MDA pInvokeStackImbalance ao depurar.Uma pilha desequilibrada pode passar despercebida por um tempo, ela tende a travar seu programa na versão de lançamento.
Ilya, você também pode definir a convenção de chamada padrão em Propriedades do projeto -> Propriedades de configuração -> C / C ++ -> Avançado -> Convenção de chamada. Se a convenção de chamada padrão em seu projeto já estiver definida para __stdcall (/ Gz), adicione __std