Вопрос

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

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 - это определенный объявлено.

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

Это было полезно?

Решение

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

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

extern TWinDynDriverCallbacks WinDynDriverCallbacks;

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

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

TWinDynDriverCallbacks WinDynDriverCallbacks;

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

Другие советы

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

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

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

extern "C" ERL_NIF_INIT(...)

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

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

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

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

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

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

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

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

После этого он стал чистым.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top