我创建了一个DLL(比如说CORE.DLL),我的类/函数声明如下:
#ifdef RINZOCORE_SHARED
#define RINZO_LIB __declspec(dllexport)
#else
#define RINZO_LIB __declspec(dllimport)
#endif
我使用“dllexport”宏定义了许多内联函数,
class RINZO_LIB CVector
{
public:
CVector();//!< default constructor
..
real& x();//!< accessor for the x component (can be used as l-value too)
real& y();//!< accessor for the y component (can be used as l-value too)
real& z();//!< accessor for the z component (can be used as l-value too)
CVector& operator=(const CVector& other);//!< the assignment
CVector& operator+=(const CVector& other);//!< the sum & assign
CVector& operator-=(const CVector& other);//!< the subtract & assign
CVector& operator*=(const real& fact);//!< the short multiply by a scalar factor & assign
CVector& operator/=(const real& fact);//!< the short divide by a scalar factor & assign
..
}
RINZO_LIB inline CVector& CVector::operator=(const CVector& other)
{
//check for 'a=a' case
if (this==&other) return *this;
vec[0]=other.vec[0];
vec[1]=other.vec[1];
vec[2]=other.vec[2];
return *this;
}
RINZO_LIB inline CVector& CVector::operator+=(const CVector& other)
{
vec[0]+=other.vec[0];
vec[1]+=other.vec[1];
vec[2]+=other.vec[2];
return *this;
}
RINZO_LIB inline CVector& CVector::operator-=(const CVector& other)
{
vec[0]-=other.vec[0];
vec[1]-=other.vec[1];
vec[2]-=other.vec[2];
return *this;
}
RINZO_LIB inline CVector& CVector::operator*=(const real& fact)
{
vec[0]*=fact;
vec[1]*=fact;
vec[2]*=fact;
return *this;
}
RINZO_LIB inline CVector& CVector::operator/=(const real& fact)
{
assert(fabs(fact) >= epsilon);
vec[0]/=fact;
vec[1]/=fact;
vec[2]/=fact;
return *this;
}
但是当我使用这个DLL(import)编译另一个DLL(比如PluginA.DLL)时,它会产生以下编译错误:
Info: resolving std::cout by linking to __imp___ZSt4cout (auto-import)
CMakeFiles\ContourViewer.dir/objects.a(RzStateDoAnimation.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/statemachine/RzStateDoAnimation.cpp:79: undefined reference to `operator!=(quaternion const&, quaternion const&)'
Info: resolving vtable for __cxxabiv1::__vmi_class_type_info by linking to __imp___ZTVN10__cxxabiv121__vmi_class_type_infoE (auto-import)
CMakeFiles\ContourViewer.dir/objects.a(RzStateDoAnimation.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/statemachine/RzStateDoAnimation.cpp:146: undefined reference to `operator==(quaternion const&, quaternion const&)'
CMakeFiles\ContourViewer.dir/objects.a(BallController.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/trackball/BallController.cpp:159: undefined reference to `operator*(CVector const&, CVector const&)'
CMakeFiles\ContourViewer.dir/objects.a(BallController.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/trackball/BallController.cpp:165: undefined reference to `operator^(CVector const&, CVector const&)'
CMakeFiles\ContourViewer.dir/objects.a(BallController.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/trackball/BallController.cpp:168: undefined reference to `operator-(CVector const&, CVector const&)'
CMakeFiles\ContourViewer.dir/objects.a(BallController.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/trackball/BallController.cpp:292: undefined reference to `operator*(CVector const&, CVector const&)'
CMakeFiles\ContourViewer.dir/objects.a(BallController.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/trackball/BallController.cpp:292: undefined reference to `operator*(CVector const&, float const&)'
CMakeFiles\ContourViewer.dir/objects.a(BallController.cpp.obj):C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/contourviewer/trackball/BallController.cpp:292: undefined reference to `operator-(CVector const&, CVector const&)'
有关如何在dllexport / dllimport中使用内联函数的任何提示?
答案 0 :(得分:8)
内联和dllexport / dllimport不要混用。
你要么
尝试同时做这两件事没有多大意义。
从每个兼容两者的函数定义中删除inline
或RINZO_LIB
,您应该没问题。
编辑为了消除任何误解: 可以导出和导入内联函数,事实上只需在声明上放置dllexport / dllimport即可。< / p>
答案 1 :(得分:4)
我想提供一些额外的信息,因为这是一个非常棘手的问题,并且有一些关于内联导出/导入的错误信息。
首先:内联函数可以与dllimport / dllexport一起使用而没有问题。意思是完全合理的:你提供了一个内联定义,可以在你的DLL内部使用,也可以在客户端代码外部使用(可以内联它,但仍然可以访问,就好像它是一个标准的导出函数。换句话说,如果需要,您仍然可以获得指向DLL 中驻留的函数实现的指针。例如,用例包括通过FFI访问函数,能够访问内存分配/自由例程,这些例程应该在模块中内联,但需要使用DLL的impl用于跨越DLL边界的内存等。
请参阅https://blogs.msdn.microsoft.com/oldnewthing/20140109-00/?p=2123以获得彻底的处理,并澄清同时内联和导出/导入的含义。
接下来,在您的具体情况下,我发现您尝试做的事情没有立即出错。您希望为自己和客户提供快速的内联矢量数学,同时仍然可以像访问标准导出那样访问该功能。如果最后一位不是真的(即,你没有明确需要指向DLL的函数实现的指针,那么评论/答案是正确的:删除导出/导入并使其成为.hpp的一部分。仅当您知道仍需要访问DLL的函数导出版本时,才使用import / export + inline 。同样,这是一个完全合理的事情,但是,它通常不是 所需的 - 所以请确保你确实需要它。
所有这一切,看起来你的DLL没有导出符号。
仔细检查以确保在构建库时定义RINZOCORE_SHARED
。检查DLL的符号,看看是否已导出这些功能(如果没有,并且您已经定义了RINZOCORE_SHARED
,那么我真的很难过)
检查以确保您在任何需要调用此功能的位置包含具有功能定义的标题。检查以确保您的插件版本中未定义RINZOCORE_SHARED
。看起来您的插件正在尝试查找函数的导出版本,这似乎意味着它没有这些内联函数的定义。
我通常只在C-linkage函数中使用它,所以老实说我不太确定在C ++ ABI方面会出现什么问题。