Смущает неразрешенная внешняя ошибка символа - PullRequest
1 голос
/ 28 августа 2009

Я пытаюсь создать библиотеку оболочки с помощью компилятора 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

Когда я пытаюсь построить это, я получаю следующую ошибку компоновщика:

ErlDriver.obj: ошибка LNK2019: неразрешенный внешний символ _WinDynDriverCallbacks, на который ссылается функция __driver_output

erl_win_dyn_driver.h (включено в 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)

Итак, как вы можете видеть, WinDynDriverCallbacks определено объявлено.

Тогда что может быть причиной ошибки компоновщика?

Ответы [ 4 ]

2 голосов
/ 28 августа 2009

Нет, это не определено (по крайней мере в том, что вы цитировали). Это объявлено. Ключевое слово «extern» означает «определение для этого символа появляется в другом модуле компиляции (исходный файл)». Необходимо связать объектный файл (или библиотеку), созданный при компиляции исходного файла, который определяет этот символ.

1 голос
/ 22 декабря 2011

У меня очень похожая проблема при создании NIF на Windows. Неразрешенный внешний символ _WinDynNifCallbacks. Оказывается, это определяется макросом ERL_NIF_INIT, и в моем случае весь макрос необходимо было заключить во внешний блок C.

то есть это не удалось

extern "C" ERL_NIF_INIT(...)

пока это удалось

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

Я сильно подозреваю, что эта проблема связана с той же проблемой, но с макросом DRIVER_INIT для драйвера порта erlang.

1 голос
/ 28 августа 2009

Существует небольшая разница между "объявлением" чего-либо и "определением" этого в C или C ++. Когда вы объявляете это, он сообщает компилятору, что определенный символ будет определен где-то еще - это может позволить коду использовать этот символ без необходимости видеть фактическое определение. Вам все еще нужно определить символ где-то в коде, который связан с, иначе вы получите сообщение об ошибке, которое вы видите.

Например, это объявление символа WinDynDriverCallbacks:

extern TWinDynDriverCallbacks WinDynDriverCallbacks;

Ваш код имеет это объявление - он позволяет коду, использующему символ, успешно компилироваться (но не по ссылке).

Вам нужно где-то добавить определение:

TWinDynDriverCallbacks WinDynDriverCallbacks;

Определение должно быть где-то в файле исходного кода (обычно не в заголовочном файле). Это говорит компилятору выделить место в объектном коде для этого объекта и позволяет программе успешно связываться.

0 голосов
/ 14 февраля 2013

Driver_Init - это основной цикл, который объявляет "TWinDynDriverCallbacks WinDynDriverCallbacks;" но он правильно объявлен в многострочном определении для driver_init. Вам не нужно оборачивать его во внешнюю "c".

так как эта тема возникала около миллиона раз при попытке установить мой драйвер порта barebones erlang, я скажу это здесь. Я работаю над книгой Эрланга по программированию Джо Армстронга, глава 12 «Методы взаимодействия». Используя erl5.9 и vs2010.

В коде из книги было пропущено сообщение об ошибке в example1_lib.c. Хотя ошибка, скорее всего, связана с изменением возраста книги и версии на эрланге.

Необходимо установить (#define WIN32 ) в самом верху example1_lib.c, в противном случае erlang будет по умолчанию для всех параметров Linux.

Секунду, необходимую для изменения (int bufflen) на (ErlDrvSizeT bufflen) в example_drv_output.

После этого он выстроился чисто.

...