Pergunta

Estou tentando construir uma biblioteca de wrapper com o compilador do VC ++.

Erldriver.c

#define __WIN32__
#define DLL_EXPORT __declspec(dllexport)

#include "erl_driver.h"

DLL_EXPORT int _driver_output(ErlDrvPort port, char *buf, int len) {
    return driver_output(port, buf, len);
}

build.bat

cl /I%ERL_DRIVER_H% /LD /MD ErlDriver.c

Quando tento construir isso, recebo o seguinte erro do vinculador:

Erldriver.obj: erro lnk2019: símbolo externo não resolvido _windyndrivercallbacks referenciados na função __driver_output

erl_win_dyn_driver.h (incluído em erl_driver.h)

typedef struct {
    WDD_FTYPE(driver_output) *driver_output;
    // a ton more of those
} TWinDynDriverCallbacks;

extern TWinDynDriverCallbacks WinDynDriverCallbacks;

#define driver_output (WinDynDriverCallbacks.driver_output)

Então, como você pode ver, WindyndriverCallbacks é definiram declarado.

O que poderia estar causando o erro do vinculador, então?

Foi útil?

Solução

Há uma diferença sutil entre "declarar" algo e "definir" em C ou C ++. Quando você o declara, ele diz ao compilador que um determinado símbolo será definido em outro lugar - isso pode permitir que o código use esse símbolo sem precisar ver a definição real. Você ainda precisa definir o símbolo em algum lugar do código vinculado, ou então receberá a mensagem de erro que está vendo.

Por exemplo, esta é uma declaração do símbolo WinDynDriverCallbacks:

extern TWinDynDriverCallbacks WinDynDriverCallbacks;

Seu código tem essa declaração - permite que o código que usa o símbolo para compilar com sucesso (mas não link).

Você precisa adicionar uma definição em algum lugar:

TWinDynDriverCallbacks WinDynDriverCallbacks;

A definição deve entrar em um arquivo de código -fonte em algum lugar (geralmente não em um arquivo de cabeçalho). Isso diz ao compilador para alocar espaço no código do objeto para esse objeto e permite que o programa vincule com sucesso.

Outras dicas

Não, não está definido (pelo menos no que você citou). É declarado. A palavra -chave "externa" significa "a definição para este símbolo aparece em outra unidade de compilação (arquivo de origem)." Você precisa vincular o arquivo de objeto (ou biblioteca) produzido a partir da compilação do arquivo de origem que define esse símbolo.

Eu tenho um problema muito semelhante construindo um NIF nas janelas. Símbolo externo não resolvido _WindynnifCallbacks. Acontece que isso é definido pela macro erl_nif_init e, no meu caso, toda a macro precisava ser fechada em um bloco extern c.

ou seja, isso falhou

extern "C" ERL_NIF_INIT(...)

enquanto isso teve sucesso

extern "C"
{
   ERL_NIF_INIT(...)
}

Suspeito fortemente que esse problema seja devido ao mesmo problema, mas com a macro driver_init para um driver de porta Erlang.

Driver_init é o principal loop que declara "twindyndrivercallbacks windyndrivercallbacks"; Mas é declarado corretamente na linha múltipla definida para driver_init. Você não deve precisar envolvê -lo em extern "C".

Desde que esse tópico surgiu cerca de um milhão de vezes enquanto tentava configurar meu driver de porto de Erlang Barebones, direi isso aqui. Estou trabalhando no livro Erlang de Programação de Joe Armstrong, Técnicas de Interface do Capítulo 12. Usando ERL5.9 e VS2010.

O código no livro teve uma omissão e um erro no exemplo1_lib.c. Embora o erro seja provavelmente devido à idade do livro versus a versão Erlang muda.

Precisava definir (#define Win32) na parte superior do exemplo1_lib.c, caso contrário, o Erlang não fez as opções do Linux.

Segundo necessário para alterar (int bufflen) para (erldrvsizet bufflen) em exemplo_drv_output.

Depois disso, construiu limpo.

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