我正在编写一个C / C ++ DLL,想要在使用像这样的.def文件之前导出我已经完成的某些功能

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

使用定义为此的代码,例如:

int Foo(int a);
void Bar(int foo);

但是,如果我想声明一个Foo()的重载方法,如下所示:

int Foo(int a, int b);

由于def文件只有函数名而不是完整的原型,我无法看到它如何处理重载函数。 您是否只使用一个条目,然后在将正确的原型函数指针传递给LoadLibrary()时指定您想要的重载版本?

编辑:要清楚,这是在使用Visual Studio 2005的Windows上

编辑:将非def(__ declspec)方法标记为答案...我知道这实际上并没有像我想的那样使用def文件解决问题,但似乎很可能没有使用def文件的(官方)解决方案。 但是,如果有人知道我们没有重载函数和def文件,我们会将问题保持打开状态。

===============>>#1 票数:11

函数重载是一种C ++特性,它依赖于名称修改(链接器错误消息中的神秘函数名称)。

通过将损坏的名称写入def文件,我可以将我的测试项目链接并运行:

LIBRARY "TestDLL"
EXPORTS
    ?Foo@@YAXH@Z
    ?Foo@@YAXHH@Z

似乎有用

void Foo( int x );
void Foo( int x, int y );

因此,从错误消息中复制C ++函数名称并将其写入def文件。 但是,真正的问题是:为什么要使用def文件而不是__declspec(dllexport)?

受损的名称是不可移植的,我使用VC ++ 2008进行了测试。

===============>>#2 票数:9 已采纳

在代码本身中,使用__declspec(dllexport)标记要导出的函数。 例如:

#define DllExport __declspec(dllexport)

int DllExport  Foo( int a ) {
  // implementation
}
int DllExport Foo( int a, int b ) {
  // implementation
}

如果执行此操作,则无需在.def文件中列出这些函数。

或者,您可以使用默认参数值,例如:

int Foo( int a, int b = -1 )

这假定存在一个b值,可用于指示它未使用。 如果-1是b的合法值,或者如果没有或不应该是默认值,则这将不起作用。

编辑(Adam Haile):更正使用__declspec作为__dllspec不正确所以我可以将其标记为正式答案......它足够接近。

编辑(格雷姆):哎呀 - 感谢纠正我的错字!

===============>>#3 票数:8

我有类似的问题,所以我也希望发布这个问题。

  1. 通常使用

     extern "C" __declspec(dllexport) void Foo(); 

    导出函数名称很好。 通常会输出名称unmangled而不需要.def文件。 但是,有一些例外,例如__stdcall函数和重载函数名。

  2. 如果声明一个函数使用__stdcall约定(就像许多API函数一样)那么

     extern "C" __declspec(dllexport) void __stdcall Foo(); 

    将导出像_Foo @ 4这样的错位名称。 在这种情况下,您可能需要将导出的名称显式映射到内部损坏的名称。

A.如何导出未编码的名称。 在.def文件中添加

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

这将尝试为内部函数Foo找到“最佳匹配”并将其导出。 在上面只有一个foo的情况下,这将创建映射

Foo = _Foo @ 4

通过dumpbin / EXPORTS可以看到

如果您重载了一个函数名,那么您可能需要通过使用entryname [= internalname]语法指定一个受损的名称来明确说明.def文件中您想要的函数。 例如

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

B. .ff文件的替代方法是您可以使用#pragma“就地”导出名称。

#pragma comment(linker, "/export:Foo=_Foo@4")

C.第三种方法是声明只有一个版本的Foo作为外部“C”来导出未编译的。 详情请见此处

===============>>#4 票数:3

没有正式的方法可以做你想要的,因为dll接口是一个C api。

编译器本身使用损坏的名称作为变通方法,因此当您不希望在代码中进行太多更改时,应使用名称修改。

===============>>#5 票数:2

EXPORTS定义的Systax是:

entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]

entryname是要导出的函数或变量名称。 这是必需的。 如果导出的名称与DLL中的名称不同,请在DLL中使用internalname指定导出的名称。

例如,如果您的DLL导出函数func1()并且您希望将其用作func2(),则应指定:

EXPORTS
func2=func1

只需查看损坏的名称(使用Dependency walker)并指定您自己的函数名称。

资料来源: http//msdn.microsoft.com/en-us/library/hyx1zcd3(v = vs.71).aspx

编辑:这适用于动态DLL,我们需要使用GetProcAddress()显式获取Dll中的函数。

===============>>#6 票数:2

由于修改约定随编译器的每个版本而变化,因此没有一种语言或版本无关的导出重载函数的方法。

这就是为什么大多数WinXX函数都有像* Ex或* 2这样有趣的名字的原因之一。

  ask by Adam Haile translate from so

未解决问题?本站智能推荐: