Pergunta

Estou preso em uma correção para um aplicativo legado do Visual C++ 6.Na fonte C++ DLL eu coloquei

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

o que resulta na exibição de MyNewVariable (bem sem decoração) na tabela de exportação (conforme mostrado por dumpbin /exports blah.dll).No entanto, não consigo descobrir como declarar a variável para poder acessá-la em um arquivo de origem C.Eu tentei várias coisas, incluindo

_declspec(dllimport) char* MyNewVariable;

mas isso só me dá um erro de vinculador:

símbolo externo não resolvido "__declspec(dllimport) char * MyNewVariable" (__imp_?MyNewVariable@@3PADA)

extern "C" _declspec(dllimport) char* MyNewVariable;

como sugerido por Tony (e como tentei antes) resulta em uma decoração diferente do esperado, mas ainda não a removeu:

símbolo externo não resolvido __imp__MyNewVariable

Como escrevo a declaração para que a variável DLL C++ seja acessível no aplicativo C?


A resposta

Conforme identificado por botismarius e outros (muito obrigado a todos), eu precisava vincular ao .lib da DLL.Para evitar que o nome fosse mutilado, precisei declará-lo (na fonte C) sem decoradores, o que significa que precisei usar o arquivo .lib.

Foi útil?

Solução

você deve vincular-se à lib gerada após compilar a DLL.Nas opções do vinculador do projeto, você deve adicionar o .lib arquivo.E sim, você também deve declarar a variável como:

extern "C" { declspec(dllimport) char MyNewVariable; }

Outras dicas

extern "C" é como você remove a decoração - deve funcionar para usar:

extern "C" declspec(dllimport) char MyNewVariable;

ou se você quiser um cabeçalho que possa ser usado por C++ ou C (com opção /TC)

#ifdef __cplusplus
extern "C" {
#endif
declspec(dllimport) char MyNewVariable;
#ifdef __cplusplus
}
#endif

E claro, linkar com a biblioteca de importação gerada pela dll que faz a exportação.

Não tenho certeza de quem reduziu o botismarius, porque ele está certo.A razão é que o .lib gerado é a biblioteca de importação que torna mais fácil simplesmente declarar a variável/função externa com __declspec(dllimport) e apenas use-o.A biblioteca de importação simplesmente automatiza o necessário LoadLibrary() e GetProcAddress() chamadas.Sem ele, você precisa chamá-los manualmente.

Ambos estão certos.O fato de a mensagem de erro descrever __imp_?MyNewVariable@@3PADA significa que está procurando o nome decorado, portanto o "C" externo é necessário.No entanto, vincular à biblioteca de importação é também necessário ou você receberá um erro de link diferente.

@Graeme:Você está certo nisso também.Acho que o compilador "C" que o OP está usando não está aplicando o padrão C99, mas compilando como C++, distorcendo assim os nomes.Um verdadeiro compilador C não entenderia a parte “C” do extern "C" palavra-chave.

No código fonte dll você deve ter esta implementação para que o arquivo .lib exportações o símbolo:

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

O cliente c deve usar um cabeçalho com esta declaração para que o código do cliente importar o símbolo:

extern "C" _declspec(dllimport) char* MyNewVariable;

Este cabeçalho causará um erro de compilação se #include-ed no código-fonte da dll, portanto, geralmente é colocado em um cabeçalho de exportação que é usado apenas para funções exportadas e apenas por clientes.

Se necessário, você também pode criar um cabeçalho "universal" que pode ser incluído em qualquer lugar parecido com este:

#ifdef __cplusplus
extern "C" {
#endif
#ifdef dll_source_file
#define EXPORTED declspec(dllexport) 
#else
#define EXPORTED declspec(dllimport) 
#endif dll_source_file
#ifdef __cplusplus
}
#endif

EXPORTED char* MyNewVariable;

Então o código fonte da dll fica assim:

#define dll_source_code 
#include "universal_header.h"

EXPORTED char* MyNewVariable = 0;

E o cliente fica assim:

#include "universal_header.h"
...
MyNewVariable = "Hello, world";

Se você fizer muito isso, o monstro #ifdef no topo pode entrar em export_magic.h e universal_header.h se tornar:

#include "export_magic.h"

EXPORTED char *MyNewVariable;

Nunca usei _declspec(dllimport) quando estava programando no Windows.Você deve ser capaz de simplesmente declarar

extern "C" char* MyNewVariable;

e link para o .libb criado quando a DLL foi compilada.

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