Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Смущен неразрешенной ошибкой внешнего символа

Автор вопроса: David BrownОтветов: 4

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

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

clinker-errorslinkerunresolved-external

Ответы

Ответ 1 · рейтинг 1 · 1800 INFORMATION

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

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

extern TWinDynDriverCallbacks WinDynDriverCallbacks;

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

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

TWinDynDriverCallbacks WinDynDriverCallbacks;

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

Ответ 2 · рейтинг 2 · Tyler McHenry

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

Ответ 3 · рейтинг 1 · Gary

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

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

extern "C" ERL_NIF_INIT(...)

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

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

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

Ответ 4 · jason

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

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

Код в книге содержал пропуск и ошибку в example1_lib.c. Хотя ошибка, скорее всего, связана с возрастом книги и изменениями версии erlang.

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

Во-вторых, необходимо изменить (int bufflen) на (ErlDrvSizeT bufflen) в example_drv_output.

После этого построили чисто.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы