简体   繁体   English

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

[英]Overloaded functions in C++ DLL def file

I'm writing a C/C++ DLL and want to export certain functions which I've done before using a .def file like this 我正在编写一个C / C ++ DLL,想要在使用像这样的.def文件之前导出我已经完成的某些功能

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

with the code defined as this, for example: 使用定义为此的代码,例如:

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

However, what if I want to declare an overloaded method of Foo() like: 但是,如果我想声明一个Foo()的重载方法,如下所示:

int Foo(int a, int b);

As the def file only has the function name and not the full prototype I can't see how it would handle the overloaded functions. 由于def文件只有函数名而不是完整的原型,我无法看到它如何处理重载函数。 Do you just use the one entry and then specify which overloaded version you want when passing in the properly prototyped function pointer to LoadLibrary() ? 您是否只使用一个条目,然后在将正确的原型函数指针传递给LoadLibrary()时指定您想要的重载版本?

Edit: To be clear, this is on Windows using Visual Studio 2005 编辑:要清楚,这是在使用Visual Studio 2005的Windows上

Edit: Marked the non-def (__declspec) method as the answer...I know this doesn't actually solve the problem using def files as I wanted, but it seems that there is likely no (official) solution using def files. 编辑:将非def(__ declspec)方法标记为答案...我知道这实际上并没有像我想的那样使用def文件解决问题,但似乎很可能没有使用def文件的(官方)解决方案。 Will leave the question open, however, in case someone knows something we don't have overloaded functions and def files. 但是,如果有人知道我们没有重载函数和def文件,我们会将问题保持打开状态。

Function overloading is a C++ feature that relies on name mangling (the cryptic function names in the linker error messages). 函数重载是一种C ++特性,它依赖于名称修改(链接器错误消息中的神秘函数名称)。

By writing the mangled names into the def file, I can get my test project to link and run: 通过将损坏的名称写入def文件,我可以将我的测试项目链接并运行:

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

seems to work for 似乎有用

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

So copy the C++ function names from the error message and write them into your def file. 因此,从错误消息中复制C ++函数名称并将其写入def文件。 However, the real question is: Why do you want to use a def file and not go with __declspec(dllexport) ? 但是,真正的问题是:为什么要使用def文件而不是__declspec(dllexport)?

The mangled names are non-portable, I tested with VC++ 2008. 受损的名称是不可移植的,我使用VC ++ 2008进行了测试。

In the code itself, mark the functions you want to export using __declspec(dllexport). 在代码本身中,使用__declspec(dllexport)标记要导出的函数。 For example: 例如:

#define DllExport __declspec(dllexport)

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

If you do this, you do not need to list the functions in the .def file. 如果执行此操作,则无需在.def文件中列出这些函数。

Alternatively, you may be able to use a default parameter value, like: 或者,您可以使用默认参数值,例如:

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

This assumes that there exists a value for b that you can use to indicate that it is unused. 这假定存在一个b值,可用于指示它未使用。 If -1 is a legal value for b, or if there isn't or shouldn't be a default, this won't work. 如果-1是b的合法值,或者如果没有或不应该是默认值,则这将不起作用。

Edit (Adam Haile): Corrected to use __declspec as __dllspec was not correct so I could mark this as the official answer...it was close enough. 编辑(Adam Haile):更正使用__declspec作为__dllspec不正确所以我可以将其标记为正式答案......它足够接近。

Edit (Graeme): Oops - thanks for correcting my typo! 编辑(格雷姆):哎呀 - 感谢纠正我的错字!

I had a similar issue so I wanted to post on this as well. 我有类似的问题,所以我也希望发布这个问题。

  1. Usually using 通常使用

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

    to export a function name is fine. 导出函数名称很好。 It will usually export the name unmangled without the need for a .def file. 通常会输出名称unmangled而不需要.def文件。 There are, however, some exceptions like __stdcall functions and overloaded function names. 但是,有一些例外,例如__stdcall函数和重载函数名。

  2. If you declare a function to use the __stdcall convention (as is done for many API functions) then 如果声明一个函数使用__stdcall约定(就像许多API函数一样)那么

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

    will export a mangled name like _Foo@4. 将导出像_Foo @ 4这样的错位名称。 In this case you may need to explicitly map the exported name to an internal mangled name. 在这种情况下,您可能需要将导出的名称显式映射到内部损坏的名称。

A. How to export an unmangled name. A.如何导出未编码的名称。 In a .def file add 在.def文件中添加

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

This will try to find a "best match" for an internal function Foo and export it. 这将尝试为内部函数Foo找到“最佳匹配”并将其导出。 In the case above where there is only one foo this will create the mapping 在上面只有一个foo的情况下,这将创建映射

Foo = _Foo@4 Foo = _Foo @ 4

as can be see via dumpbin /EXPORTS 通过dumpbin / EXPORTS可以看到

If you have overloaded a function name then you may need to explicitly say which function you want in the .def file by specifying a mangled name using the entryname[=internalname] syntax. 如果您重载了一个函数名,那么您可能需要通过使用entryname [= internalname]语法指定一个受损的名称来明确说明.def文件中您想要的函数。 eg 例如

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

B. An alternative to .def files is that you can export names "in place" using a #pragma. B. .ff文件的替代方法是您可以使用#pragma“就地”导出名称。

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

C. A third alternative is to declare just one version of Foo as extern "C" to be exported unmangled. C.第三种方法是声明只有一个版本的Foo作为外部“C”来导出未编译的。 See here for details. 详情请见此处

There is no official way of doing what you want, because the dll interface is a C api. 没有正式的方法可以做你想要的,因为dll接口是一个C api。

The compiler itself uses mangled names as a workaround, so you should use name mangling when you don't want to change too much in your code. 编译器本身使用损坏的名称作为变通方法,因此当您不希望在代码中进行太多更改时,应使用名称修改。

Systax for EXPORTS definition is: EXPORTS定义的Systax是:

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

entryname is the function or variable name that you want to export. entryname是要导出的函数或变量名称。 This is required. 这是必需的。 If the name you export is different from the name in the DLL, specify the export's name in the DLL with internalname. 如果导出的名称与DLL中的名称不同,请在DLL中使用internalname指定导出的名称。

For example, if your DLL exports a function, func1() and you want it to be used as func2(), you would specify: 例如,如果您的DLL导出函数func1()并且您希望将其用作func2(),则应指定:

EXPORTS
func2=func1

Just see the mangled names (using Dependency walker) and specify your own functions name. 只需查看损坏的名称(使用Dependency walker)并指定您自己的函数名称。

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

Edit: This works for dynamic DLLs, where we need to use GetProcAddress() to explicitly fetch a functions in Dll. 编辑:这适用于动态DLL,我们需要使用GetProcAddress()显式获取Dll中的函数。

There isn't a language or version agnostic way of exporting an overloaded function since the mangling convention can change with each release of the compiler. 由于修改约定随编译器的每个版本而变化,因此没有一种语言或版本无关的导出重载函数的方法。

This is one reason why most WinXX functions have funny names like *Ex or *2. 这就是为什么大多数WinXX函数都有像* Ex或* 2这样有趣的名字的原因之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM