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.

Foi útil?

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:

  1. __declspec(dllexport) declara sua função como uma função pública que sua DLL exporta;

  2. __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;

  3. 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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top