1

我正在尝试使用 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);
}

构建.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

4 回答 4

2

不,它没有定义(至少在你引用的内容中)。宣布了。“extern”关键字的意思是“这个符号的定义出现在另一个编译单元(源文件)中”。您需要与通过编译定义该符号的源文件生成的目标文件(或库)进行链接。

于 2009-08-27T21:21:55.377 回答
1

在 C 或 C++ 中“声明”和“定义”之间存在细微差别。当您声明它时,它会告诉编译器某个符号将在其他地方定义 - 这可以允许代码使用该符号而无需查看实际定义。您仍然必须在链接的代码中的某处定义符号,否则您将收到您所看到的错误消息。

例如,这是符号的声明WinDynDriverCallbacks

extern TWinDynDriverCallbacks WinDynDriverCallbacks;

您的代码具有此声明 - 它允许使用该符号的代码成功编译(但不能链接)。

您需要在某处添加定义:

TWinDynDriverCallbacks WinDynDriverCallbacks;

定义必须进入某个源代码文件(通常不在头文件中)。这告诉编译器在对象代码中为该对象分配空间,并允许程序成功链接。

于 2009-08-27T21:38:07.713 回答
1

我在 Windows 上构建 NIF 时遇到了非常相似的问题。未解析的外部符号 _WinDynNifCallbacks。原来这是由 ERL_NIF_INIT 宏定义的,在我的情况下,整个宏需要包含在 extern C 块中。

即这失败了

extern "C" ERL_NIF_INIT(...)

虽然这成功了

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

我强烈怀疑这个问题是由于相同的问题,但与 erlang 端口驱动程序的 DRIVER_INIT 宏有关。

于 2011-12-22T11:51:59.727 回答
0

Driver_Init 是声明“TWinDynDriverCallbacks WinDynDriverCallbacks;”的主循环 但它已在 driver_init 的多行定义中正确声明。您不需要将其包装在 extern "c" 中。

因为这个线程在尝试设置我的准系统 erlang 端口驱动程序时出现了大约一百万次,所以我会在这里说这个。我正在研究 Joe Armstrong 的编程 erlang 书,第 12 章接口技术。使用 erl5.9 和 vs2010。

书中代码在example1_lib.c中有遗漏和错误。尽管该错误很可能是由于书的年龄与 erlang 版本的变化有关。

需要在 example1_lib.c 的最顶部设置 (#define WIN32 ) 否则 erlang 默认为所有 Linux 选项。

第二个需要在 example_drv_output 中将 (int bufflen) 更改为 (ErlDrvSizeT bufflen)。

之后它建立干净。

于 2013-02-14T19:44:29.663 回答