当前位置:  开发笔记 > 编程语言 > 正文

C++ DLL def文件中的重载函数

如何解决《C++DLLdef文件中的重载函数》经验,为你挑选了3个好方法。

我正在编写一个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> Timbo..:

函数重载是一种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> Graeme Perro..:

在代码本身中,使用__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不正确所以我可以将其标记为正式答案......它足够接近.

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


然后你需要使用受损的名称,或者重命名其中一个函数并使它们都成为"extern"C"`,假设它们都不接受或返回C++对象.

3> 小智..:

我有一个类似的问题,所以我也想发布这个问题.

    通常使用

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

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

    如果声明一个函数使用__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声明为extern"C",以便解除输出.详情请见此处.

推荐阅读
linjiabin43
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有