2014-01-23 35 views
1

我有一个类,它在我的软件的所有代码中被广泛使用。该类是具有几何几何函数的点抽象,并且按坐标类型(例如long或double)进行模板化。如果在动态库之间传递了这一点,我会收到编译器警告C4252:类'Point'需要dll接口供'OtherClass'类的客户端使用,但代码运行良好且快速,因为所有库都具有相同的编译设置。如何保持内置调用但避免编译器警告?

由于我们的政策是没有任何警告,在所有我们决定,以纪念两种广泛使用的模板特DLL导出的这样的(在头与模板):

template class __declspec(dllexport) Point<long>; 
template class __declspec(dllexport) Point<double>; 

但是现在的编译器替换共同所有的内联函数调用,因为这个类被大量使用,我们的代码变得更慢。

现在的问题是:有没有什么方法可以在每个使用库的地方保持调用内联,但仍然在dll之间传递数据并避免警告?

我们使用Microsoft VC++ 2012编译器。

+0

根据我的经验,如果速度是我使用静态链接代码,而不是DLL文件,为你准确描述的原因,然而,回想起来实现更好的性能的问题,我觉得thjere可能会有一些方法来达到你是什么尽管我怀疑基准测试仍然会显示静态链接的代码更快。我正在研究强制dll在加载时驻留内存,以便可以实现与内置/静态链接代码类似的性能。我会在今天晚些时候回复你:) – GMasucci

+0

问题不在于将调用从静态变为动态,而是将内联函数更改为通用调用函数。只要你标记你的类/函数的DLL导出,你不会再有任何内联函数。 – Dmytro

+0

是的,这又回到了静态/动态链接:如果编译器不知道函数后面代码的具体细节,那么在编译时你不能在编译时使用“内联”代码。源代码必须在编译时可用于内联到调用位置,此时DLL会变得不必要,因为代码已经在exe中。 – GMasucci

回答

0

根据我的经验,如果速度是我使用静态链接代码/头只inlinefastcall代码,而不是DLL S,整整但是你描述的原因,取得了较好的性能问题,在回想起来,我觉得有可能是某种方式来实现你所说的,虽然我怀疑基准测试仍然会显示静态链接代码更快。

我期待到迫使DLL s到是常驻内存在加载时(和确实能够做到这一点按文章here),这样类似的性能的内联/静态链接的代码就可以实现。

这似乎起初工作,但如果加载DLL的内存在任何时候被分页,它将变得像动态访问DLL代码一样慢。

直到我研究链接到DLL S的另外的方法我个人建议inlinefastcall代码,如果这是一种选择,尽管这会导致可执行文件变大,如果内存占用可能会影响你的发布一个问题。

作为一个快速修复你上面你提到的可以尝试改变两行:

template class __declspec(dllexport) Point<long>; 
template class __declspec(dllexport) Point<double>; 

extern template class __declspec(dllexport) Point<long>; 
extern template class __declspec(dllexport) Point<double>; 

应该尽可能消除您遇到的问题。 (关于这样做的更多信息here,在该页面上用于导出STL类的实例或包含STL类的对象,这似乎是相同的问题)。然而,内联原则(编译阶段“优化”)天生就与DLL的导出/导入相反:前者通过将所有内容拼凑在一个包中来优化速度,后者则优化内存占用空间/模块化通过将代码分离成可根据需要调用的不同较小的包。

注:

  1. fastcall地方的一个或多个自变量到寄存器, 从而减少执行所需的内存的调用次数。

    • 对于MSoft和GCC,当只有2个参数时,您将获得最显着的速度优势。
    • Borland的编译器都允许最多3个寄存器/参数使用
  2. 还要注意的是inline关键字并不能保证代码将 内联,它仅仅是一个极其强烈建议下到 编译器,但是其他优化标志可能会将其删除或将您未标记为内联的其他部分内联。

希望这会有所帮助,但一如既往,如果您需要任何详细信息/帮助,请让我知道。 :)

+0

支持inline/dllexport/dllimport不兼容也发现[在其他地方](http://stackoverflow.com/questions/8876279/c-inline-functions-with-dllimport-dllexport) – GMasucci