Pergunta

Eu aviso na documentação do MSDN que existem várias maneiras para declarar uma referência a uma função em um DLL externa a partir de um programa VB.NET.

A coisa confusa é que as reivindicações do MSDN que você só pode usar o DllImportAttribute classe com protótipos função compartilhada" em casos raros "mas eu não conseguia encontrar a explicação para esta afirmação, enquanto você pode simplesmente usar o Declare palavra-chave em seu lugar.

Por que estes diferentes, e onde eu iria usar apropriadamente cada caso?

Foi útil?

Solução

Declare é realmente uma tentativa de manter um P / Invoke sintaxe que seria mais familiar para usuários Visual Basic 6.0 conversão para VB.NET . Ele tem muitos dos mesmos recursos que P / Invoke, mas a mobilização de certos tipos, em cordas particulares, são muito diferentes e pode causar um pouco de confusão para as pessoas mais familiarizadas com as regras DllImport.

Eu não sou inteiramente certo o que a documentação está aludindo com a distinção "raro". Eu uso DllImport no meu código com frequência tanto VB.NET e C # sem problema.

Em geral, eu usaria DllImport sobre Declare a menos que você vem de um fundo Visual Basic 6.0. A documentação e as amostras para DllImport são muito melhores e existem muitas ferramentas destinadas a gerar declarações DllImport.

Outras dicas

Aparentemente, a declarar e declarações DllImport são basicamente os mesmos. Você pode usar o que você preferir.

A seguir é uma discussão dos poucos pontos que podem trabalhar um pouco diferente em cada um, o que pode influenciar uma preferência por um sobre o outro:

Eu comecei com um artigo do MSDN sobre Visual Studio 2003 intitulado Usando Atributo DllImport. (Um pouco velho, mas desde que a declaração DllImport parece ter se originado em .NET, pareceu apropriado para voltar ao começo.)

Dada uma declaração exemplo DllImport de:

[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)]
int MessageBox(void* hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned int uType);

Ele diz que se o valor EntryPoint é deixado de fora, o CLR vai olhar para o nome da função (MessageBox , neste caso) como um padrão. No entanto, neste caso, uma vez que um CharSet de Unicode foi especificado, o CLR deve primeiro procurar uma função chamada "MessageBoxW" - a 'W', indicando um tipo de retorno Unicode. (A versão ANSI tipo de retorno seria "MessageBoxA".) Se nenhum "MessageBoxW" foram encontrados, então o CLR iria procurar uma função API realmente chamado "MessageBox".

especificidades atuais sobre a classe DllImportAttribute podem ser encontrados aqui, onde eu vi a versão .NET Framework 4: DllImportAttribute Classe

Um comentário chave na seção de comentários deste .NET Framework 4 página é que:

Você pode aplicar esse atributo diretamente para C # e definições de métodos C ++; No entanto, o compilador Visual Basic emite este atributo quando você usa a instrução Declare.

Assim, pelo menos no que diz respeito ao VB.NET, o compilador termina com uma declaração Declare de qualquer maneira.

Há também uma nota importante nesta página:

O DllImportAttribute não suporta empacotamento de tipos genéricos.

Assim, parece que se você quiser usar um tipo genérico, você teria que usar uma declaração Declare.

Em seguida, eu fui para a informação instrução Declare. A versão Studio 2010 Visual (Informações básicas Visual declaração) foi aqui: instrução DECLARE

Um item chave aqui foi esta nota:

Você pode usar declarar apenas no nível de módulo. Isto significa que o contexto da declaração para uma referência externa deve ser uma classe, estrutura ou módulo, e não pode ser um arquivo fonte, namespace, interface, procedimento ou bloco.

Aparentemente, se você quiser configurar uma fora chamada de API de uma classe, estrutura ou módulo, você vai ter que usar a instrução DllImport em vez do Declare.

A declaração exemplo Declare desta página é:

Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" (
  ByVal lpBuffer As String, ByRef nSize As Integer) As Integer

A seguir esse exemplo é este pequeno pedacinho de informação:

O DllImportAttribute fornece uma maneira alternativa de usar funções em código não gerenciado. O exemplo a seguir declara uma função importada sem usar uma instrução Declare.

seguido de, é claro, um exemplo de uso DllImport.

Em relação Unicode vs resultados ANSI, de acordo com esta página Declare, se você especificar um valor CharSet (disponível em Declare, mas não mostrado no exemplo acima), o CLR irá fazer o mesmo tipo de pesquisa automática de nome que DllImport faz - para Unicode ou ANSI.

Se você não especificar um valor CharSet na demonstração Declare, então você deve certificar-se de que o seu nome da função no Declare é o mesmo que o nome da função no arquivo de cabeçalho da função API real, ou você deve especificar um valor de Alias que corresponde ao nome função real no ficheiro de cabeçalho (como indicado no exemplo acima).

Eu não era capaz de encontrar qualquer específica documentação Microsoft afirmando que quer DllImport ou declarar foram preferidos, ou mesmo recomendado, uns sobre os outros em qualquer situação que não os mencionados acima.

A minha conclusão, portanto, é:

1) A menos que você precisa colocar a sua definição em um dos lugares uma declaração Declare não podem ser utilizados, quer técnica irá funcionar bem,

e

2) se você estiver usando DllImport, certifique-se de especificar o valor CharSet você quer (Unicode ou ANSI), ou você pode obter resultados inesperados.

Na minha opinião, uma vez que esta palavra-chave não parece deprected, etc. pelo que procurou, basta usar palavras-chave em tempo de compilação em vez de atributos.

Além disso, quando você usa o Declare, você não precisa escrever o End Function. A vantagem disso é que você pode criar um módulo inteiro de declarações de linha de importações de função por linha, sem a necessidade de pulute seu código com DllImports e End Functions.

Quando você declara utilizando palavras-chave Declare, o compilador trata esta função como Shared qualquer maneira, então ele pode ser acessado através de outros objetos extenal.

Mas eu acho que no VB.NET atual ambos estão dirigidas para o mesmo destino e nenhuma diferença de desempenho - nenhuma garantia em um presente

.

Assim, a minha conclusão é: Do utilizar o Declare vez de DllImport , especialmente de ler o que você citou que Microsoft afirmou que ele deve ser usado em casos raros.

Se você precisa definir uma das seguintes opções, então use atributo DllImportAttribute, uso Declare mais. De https://msdn.microsoft.com/en-us/library/w4byd5y4. aspx

Para aplicar o BestFitMapping, CallingConvention, ExactSpelling, PreserveSig, SetLastError ou campos ThrowOnUnmappableChar a um Microsoft Visual Basic 2005 declaração, você deve usar o atributo DllImportAttribute em vez da instrução Declare.

Não está claro a partir da referência acima só se se aplica a apenas "Visual Basic 2005" ou não, como referência acima é de um artigo .NET 4.5. No entanto, eu também encontrei este artigo ( https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute (v = vs.110) .aspx ), que é específico para a classe DllImportAttribute em .NET 4.5 :

o compilador Visual Basic emite este atributo quando você usa o declaração Declare. Para definições de métodos complexos que incluem BestFitMapping, CallingConvention, ExactSpelling, PreserveSig, SetLastError ou ThrowOnUnmappableChar campos, de aplicar esta atributo diretamente para definições de Visual Basic Método .

Isto diz-lhe que a opção Declare é VB.net açúcar sintática que é convertido em DllImportAttribute em tempo de compilação, e descreve os cenários exatas quando utilizar DllImportAttribute diretamente é recomendado.

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