Artigo: 106553 - Última revisão: quinta-feira, 15 de Julho de 2004 - Revisão: 2.1

Como escrever DLL C e chamá-los a partir do Visual Basic

Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.

Nesta página

Expandir tudo | Reduzir tudo

Sumário

Este artigo descreve como utilizar as DLL com o Visual Basic. Ele abrange os seguintes problemas:

A secção

  • 1.0 o que é uma DLL?
  • 1.1 Porquê utilizar uma DLL?
  • 1.2 Anatomia de uma DLL.
  • Problemas de gestão de memória DLL 1.3.
  • 1.4 Construir uma DLL utilizando o Visual C++.
  • DLL de 1,5 exemplo C.

Secção B

  • 2.0 Dll a chamar a partir do Visual Basic.
  • Parâmetros DLL 2.1.
  • 2.2 Resolução de problemas.
  • 2.3 Exemplo do Visual Basic chamadas programas.

Mais Informação

A SECÇÃO

1.0 o que é uma DLL?

Dll (bibliotecas de ligação dinâmica) são um aspecto importante do Windows. Uma DLL contém funções que pode chamar o programa executável durante a execução. Por outras palavras, uma DLL é uma biblioteca de funções que o programa pode ligar a dinamicamente.

Uma hiperligação pode ser estático ou dinâmico. Não alteram ligações estáticas. Todas as informações endereço necessárias pelo programa para aceder a função biblioteca são corrigidas quando o ficheiro executável é criado e permanece sem alterações durante a execução.

São criadas hiperligações dinâmicas conforme necessário. Quando o programa necessita de uma função que não está num ficheiro executável, o Windows carrega biblioteca de hiperligação dinâmica (DLL), disponibilizar todas as respectivas funções para a aplicação. Nessa altura, o Windows resolve o endereço de cada função e dinamicamente liga-a à sua aplicação.

Todos os controlos personalizados utilizados no Visual Basic são dll. A única diferença é que requerem um tratamento especial em termos de mensagens recebidas a partir do Visual Basic.

1.1 Porquê utilizar dll?

Seguem-se quatro razões por que razão poderá pretender utilizar uma DLL:

  • Acesso a funções C de tempo de execução:

    A biblioteca de tempo de execução C tem muitas funções útil não estaria disponíveis para programadores do Visual Basic foram-não dll. Por exemplo, a função _dos_getdiskfree permite-lhe calcular a quantidade de espaço em disco e o espaço livre disponível numa unidade.
  • Acesso à API (Application Programming Interface) do Windows funções que requerem rotinas de chamada de retorno:

    Algumas funções da API do Windows requerem uma função de chamada de retorno. Uma função de chamada de retorno é uma função que o Windows irá invocar ao executar a API de chamada. Um exemplo deste tipo de função é EnumTaskWindows fornecerá a alça de todas as janelas pertencentes uma determinada tarefa.
  • Velocidade:

    C é uma linguagem totalmente compilada que funciona com um nível é bastante próximo código nativo do computador. Isto significa que a execução de programas que estão bem escritos em C será rápida.
  • Carregar utilizar:

    Código e dados de uma DLL são carregados apenas quando necessário. Pode ser organizada uma DLL que apenas partes obrigatórias são carregados por oposição a DLL todo. Isto reduz a quantidade de memória necessária e o tempo decorrido para carregar.

1.2 Anatomia de uma DLL

Cada DLL tem de conter uma função LibMain e deve conter um procedimento de sair do Windows (WEP) em conjunto com as funções exportadas que podem ser chamadas por um programa executável.

  • LibMain:

    Uma DLL tem de conter a função LibMain. A função LibMain é chamada pela inicializar a DLL do sistema. LibMain é apenas uma vez--chamado quando o primeiro programa que requer a DLL é carregado. Seguem-se os parâmetros transmitidos LibMain:
    -IDENTIFICADOR: Identificador para a instância da DLL.
    -PALAVRA: Segmento de dados da biblioteca.
    -PALAVRA: Tamanho de área dinâmica para dados.
    -LPSTR: parâmetros de linha de comandos.
  • WEP:

    WEP (procedimento de sair do Windows) executa a limpeza para uma DLL antes de descarregar a biblioteca. Embora uma função de WEP, Wired Equivalent PRIVACY era necessária para cada DLL em versões anteriores do sistema operativo Windows, versão 3.1 é opcional. Uma WEP, Wired Equivalent PRIVACY deve ser incluído na definição do módulo de ficheiro (.def) no Visual C, por exemplo:
    EXPORTA
    WEP
  • Funções exportadas:

    Estas são as funções que pretende chamar a partir da DLL. Estes são indicados por _export. _export é utilizado para efeitos de compatibilidade com versões anteriores. Todas as funções que pretende chamar também terá de ser listadas no ficheiro DLL (.def).

Problemas de gestão de memória 1.3 DLL

Utilize o modelo de memória de grandes dimensões.

C armazena todas as variáveis definidas como estático ou global (definido fora de uma função) na pilha do programa espaço e C armazena todas as outras variáveis na pilha.

No modelo de pequeno e médio, todos os ponteiros são perto por predefinição. Isto significa que os dados são acedidos por desvios de 16 bits para o registo de segmento (DS) de dados ou o registo de segmento (SS) de pilha. Infelizmente, o compilador não tem maneira de saber se o desvio é de directório ou o SS. Na maioria dos programas este não seria um problema porque o DS e SS aponte para o mesmo segmento. No entanto, uma DLL, é um caso especial.

Uma DLL tem seu próprio segmento de dados mas partilha a respectiva pilha de com o programa chamador. Isto significa que o DS e a II não apontam para a mesma localização. A solução mais fácil para este problema consiste em criar a DLL do modelo de memória de grandes dimensões em todas as variáveis são referenciadas por um valor de 32 bits.

Por que razão atribuição de memória dinamicamente?

Ao atribuir memória dinamicamente é uma técnica Windows amigável. Declarar matrizes grandes de dados ocupa espaço na pilha do programa, que está limitada a 64 K, ou segmento de dados do programa, o qual desperdiçam espaço em disco e memória do Windows. É aconselhável pedir ao Windows a memória quando necessário e, em seguida, liberte-quando tiver terminado.

Ao atribuir memória

No Windows, pode atribuir dinamicamente dois tipos de memória, local e global. Memória local está limitada a 64 K e, em caso de uma DLL, memória local é partilhada com o programa que chamou a DLL. Memória global é tudo da memória disponível para o Windows depois foi carregado.

Memória local é atribuída e geridos utilizando o LocalAlloc, LocalLock LocalUnlock e LocalFree funciona--como no seguinte exemplo:
   char* pszBuffer;
   ....
   pszBuffer = (char *) LocalAlloc (LPTR, 20);
   ...
   LocalFree (pszBuffer);
				
é mais rápido ao atribuir memória local do que atribuir memória global. Mas atribuições de pilha local estão limitadas a 64 K, que tem de ser partilhado nas todos os programas que estão a chamar a DLL. É aconselhável utilizar memória local quando pequena curtos lived blocos de memória são necessários.

É atribuída memória global e geridos utilizando o GlobalAlloc, GlobalLock GlobalUnlock e GlobalFree funciona--como no seguinte exemplo:
   HGLOBAL hglb;
   char* pszBuffer;

   hglb = GlobalAlloc (GHND, 2048);
      // GHND allocates the memory as moveable and
      // initialized to 0
      // 2048 is the amount of memory to be allocated...
   pszBuffer = GlobalLock (hglb);
   ...
   GlobalUnlock (hglb);
   GlobalFree (hglb);
				
GlobalAlloc A função atribui memória em múltiplos de 4 K.

Se pretender partilhar a memória atribuída na DLL com outros programas, deve atribui-lo utilizando o sinalizador GMEM_SHARED. Se pretender partilhar a memória através de DDE, tem de atribui-lo utilizando o sinalizador GMEM_DDESHARE.

Tenha cuidado ao armazenar dados em variáveis estáticos

Se tentar armazenar dados de uma DLL utilizando variáveis globais ou estáticas, não se admire se tiverem alterado estes valores quando chamada junto a DLL. Os dados armazenados desta forma serão comuns a todas as aplicações que acedem esta DLL. Independentemente de quantas aplicações utilizam uma DLL, existe apenas uma instância da DLL. A melhor forma de contornar esta é devolver estruturas da DLL e transmiti-los novamente quando forem necessários.

Identificadores de ficheiro

Não é possível partilhar identificadores de ficheiros entre aplicações ou dll. Cada aplicação tem sua própria tabela de identificador de ficheiro. Para as duas aplicações utilizar o mesmo ficheiro utilizar uma DLL, tem ambos abri-lo individualmente.

1.4 Criação de uma DLL utilizando o Visual C++

Eis os passos necessários para criar uma DLL utilizando o Visual C++:

  1. Inicie o Visual C++.
  2. Crie um novo projecto, escolhendo o novo menu projecto. Seleccione as seguintes opções:

    • Definir o tipo de projecto à "Biblioteca ligação dinâmica (.dll) do Windows"
    • Desmarque a caixa de verificação "Utilizar Microsoft Foundation Classes".
    Pode também definir ou ver estas opções mais tarde, escolhendo Project no menu Opções.
  3. Adicione ficheiros .C e .def existentes ao projecto, utilizando a caixa de diálogo é quando pretender editar no menu Project. Ou introduza o código directamente na janela de edição do Visual C++. (Consulte o código de exemplo .C e .def listado abaixo.)
  4. No menu ' projecto ', escolha compilação <yourname>.dll opção.

DLL de 1,5 exemplo C

A seguinte DLL contém a função GetDiskInfo, que pode ser chamada a partir do Visual Basic. Irá devolver o espaço em disco disponível, o nome da unidade actual e o nome de volume.
      C Code Example, DISKINFO.C:

   #include <windows.h>
   #include <dos.h>

   int CALLBACK LibMain (HANDLE hInstance, WORD wDataSeg, WORD wHeapSize,
   LPSTR lpszCmdLine)

   // The following is required only under Windows version 3.1
   // Win32 does not require or support UnlockData()
   {
      if (wHeapSize > 0)
         UnlockData (0);  //Unlocks the data segment of the library.
      return 1;
   }

   void __export CALLBACK GetDiskInfo (char *cDrive, char *szVolumeName,
   unsigned long *ulFreeSpace)
   {
      unsigned drive;
      struct _diskfree_t driveinfo;
      struct _find_t c_file;

      _dos_getdrive (&drive);
      _dos_getdiskfree( drive, &driveinfo );

      if (!_dos_findfirst( "*.*", _A_VOLID, &c_file ))
         wsprintf( szVolumeName, "%s", c_file.name);
      else
         wsprintf ( szVolumeName, "NO LABEL");

      *cDrive = drive + 'A' -1;

      *ulFreeSpace = (unsigned long) driveinfo.avail_clusters * (unsigned
         long) driveinfo.sectors_per_cluster * (unsigned long)
         driveinfo.bytes_per_sector;
   }
				
utilize o seguinte ficheiro DISKINFO.DEF no Visual C++:
BIBLIOTECA diskinfo
Descrição 'GetDiskInfo pode ser chamado a partir do Visual Basic'
EXETYPE WINDOWS 3.1
CÓDIGO PRELOAD AMOVÍVEIS DISCARDABLE
DADOS PRELOAD ÚNICO MÓVEL
HEAPSIZE 4096
EXPORTA
GetDiskInfo @ 1
NOTA: O nome da biblioteca no ficheiro .def tem de ser a mesma que o nome do ficheiro DLL ou, então do Visual Basic, obterá "Erro ao carregar a DLL". Por exemplo, crie o ficheiro DISKINFO.DLL utilizando a instrução DISKINFO biblioteca no ficheiro .def acima.

SECÇÃO B

DLL de chamada 2.0 a partir do Visual Basic

No Visual Basic, todas as funções, incluindo funções DLL, que pretende efectuar a chamada tem primeiro de ser declarado utilizando a instrução Declare. Pode declarar as funções na secção declarações de um formulário ou um módulo. Se declarar um procedimento DLL ou função de um formulário, é privada para esse formulário. Para o tornar pública, tem de declará-lo num módulo. Segue-se um exemplo instrução Declare:
   Declare Sub getdiskinfo Lib "c:\somepath\diskinfo.dll"
      (ByVal mydrive As String, ByVal myvolume As String, free As Long)
				
tem de introduzir a instrução Declare toda como, uma única linha. Esta instrução Declare determinada declara o procedimento definido pelo utilizador que GETDISKINFO localizado no ficheiro DISKINFO.DLL criados pelo utilizador.

Depois de declarar a função, pode chamar e utilizar a função tal como seria chamar e utilizar uma função do Visual Basic.

Parâmetros DLL 2.1

Uma vez que as DLL normalmente são escritas em C, dll podem utilizar uma grande variedade de parâmetros não directamente suportados pelo Visual Basic. Como resultado, quando passar parâmetros, o programador tem de localizar o tipo de dados apropriados para passar.

Argumentos de passagem por valor ou por referência

Por predefinição, o Visual Basic passa todos os argumentos por referência. (Quando passar por referência, Visual Basic fornecerá um endereço de extremidade de 32 bits.) No entanto, muitas funções DLL esperam um argumento transmitido por valor. Isto pode ser alcançado, colocando a palavra-chave ByVal à frente da declaração argumento.

As secções seguintes mostram como converter parâmetros para o Visual Basic.

Parâmetros de numéricos de 8 a 16 bits

Passe parâmetros numéricos 8 a 16 bits (int, int curto, não assinado, curto sem sinal, BOOL e WORD) como número inteiro.

Parâmetros de numéricos de 32 bits

Passar parâmetros numéricos de 32 bits (longos e não assinados longa e DWORD) como LONG.

Identificadores de objecto

Todos os identificadores são valores de número inteiro de 16 bits exclusivo associados a uma janela e transmitidos por valor, para passar estes parâmetros como número inteiro.

Cadeias

Cadeias incluem tipos de dados LPSTR e LPBYTE (apontador de caracteres) ou apontador para caracteres não assinados. Passe estes parâmetros como (ByVal paramname como cadeia). Para passar directamente do Visual Basic cadeias, passa como (parâmetro como cadeia).

Para obter informações adicionais em cadeias de passagem entre Visual Basic e um C DLL, consulte o seguinte artigo na base de dados de conhecimento da Microsoft:
118643  (http://support.microsoft.com/kb/118643/EN-US/ ) Como passar uma cadeia ou cadeia de matriz entre o VB e uma DLL C
NOTA: as cadeias de Visual Basic requerem tratamento especial, para não passar as cadeias de directamente a menos que a DLL explicitamente requerer.

Ponteiros para valores numéricos

Transmitir apontadores para valores numéricos, simplesmente não utilizando a palavra-chave ByVal.

Estruturas

Se o tipo de Visual Basic definido pelo utilizador corresponder a estrutura esperada pela DLL, a estrutura pode ser transmitida por referência.

NOTA: Estruturas não podem ser transmitidas por valor.

Indicações para matrizes

Passe o primeiro elemento da matriz por referência.

Apontadores para funções

Visual Basic não suporta funções de chamada de retorno, pelo que funções DLL com apontadores para funções não pode ser utilizado com o Visual Basic.

Ponteiros nulos

Se uma DLL espera um apontador nulo, passá-las como (ByVal paramname como qualquer). Pode utilizar 0 & como o valor de paramname ao chamar a DLL.

Resolução de problemas 2.2

Abaixo se soluções para alguns problemas que poderá encontrar.

Recursos do sistema Manter obter inferiores depois da DLL É chamada

Lembre-se a DLL estiver a utilizar objectos GDI, tem se liberte-los depois de utilizá-los. Este poderá não ser óbvio no Visual Basic, mas quando utilizar o Windows SDK (software development kit) se criar um objecto GDI (por exemplo, CreateBrushIndirect), terá de eliminá-lo utilizando EliminarObjecto mais tarde.

Incorrecto DLL chamadas convenção erro

Este erro é frequentemente causado por omissão ou incluindo a palavra-chave ByVal da instrução Declare incorrectamente. Este erro também pode ser provocado se forem transmitidos parâmetros incorrectos.

Erro ao carregar a DLL

Este erro ocorre quando chamar um procedimento de biblioteca de ligação dinâmica e não é possível carregar o ficheiro especificado na instrução de Declare o procedimento. Pode utilizar a função de API do Microsoft Windows LoadLibrary para obter informações mais específicas sobre porque é que uma DLL Falha ao carregar.

Erro geral de protecção (GP)

Política de grupo falhas ocorrem quando o programa escreve um bloco de memória que não pertence à mesma. As duas razões mais prováveis para este são:

  • Overstepped um limite de matriz. C não verifica o índice de matriz que está a escrever é válido. Por conseguinte, pode facilmente escrever para a memória que não possui.
  • Está a utilizar um ponteiro para uma localização de memória que libertou. A melhor opção consiste em atribuir NULL para todos os ponteiros depois de libertar a respectiva memória.
Uma falha de política de grupo também pode ocorrer quando um tipo de variável incorrecto é transferido para a função DLL.

2.3 Exemplo do Visual Basic chamar programa

Existem duas partes para chamar uma DLL num programa do Visual Basic. Primeiro declare a função e, em seguida, utilizar no código de evento.

Eis um exemplo de uma instrução Declare. A instrução Declare deverá ser colocada num módulo ou na secção General Declarations de um formulário.
   ' Enter the following Declare as one, single line:
   Declare Sub getdiskinfo Lib "c:\dllartic\diskinfo.dll"

      (ByVal mydrive As String, ByVal myvolume As String, free As Long)
				
instruções ByVal especificar exactamente como é mostrado ou, então uma falha de política de grupo, poderá ocorrer.

Depois da função é declarada, é possível utilizar no código de evento. O exemplo seguinte utiliza uma função de DLL no código de evento em Command1:
   Sub Command1_Click ()
      Dim drive As String * 1
      Dim volume As String * 20
      Dim free As Long
      Call getdiskinfo(drive, volume, free)
      Text1.Text = drive
      Text2.Text = volume
      Text3.Text = Str$(free)
   End Sub
				

A informação contida neste artigo aplica-se a:
  • Microsoft Visual Basic 3.0 Professional Edition
  • Microsoft Visual Basic 3.0 Professional Edition
Palavras-chave: 
kbmt kbhowto kbprogramming KB106553 KbMtpt
Tradução automáticaTradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 106553  (http://support.microsoft.com/kb/106553/en-us/ )
Retired KB ArticleExclusão de Responsabilidade para Conteúdo sem Suporte na KB
Este artigo foi escrito sobre produtos para os quais a Microsoft já não fornece suporte. Por conseguinte, este artigo é oferecido "tal como está" e deixará de ser actualizado.