C++ :带有 dllimport/dllexport 的内联函数?

发布于 2024-12-26 22:59:38 字数 4306 浏览 6 评论 0原文

我创建了一个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(导入)时编译另一个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 一起使用的任何提示吗?

I create a DLL (say CORE.DLL) ,I have classes/functions declared as follows:

#ifdef RINZOCORE_SHARED
#define RINZO_LIB __declspec(dllexport)
#else
#define RINZO_LIB __declspec(dllimport)
#endif

I have defined many inline functions with "dllexport" macro ,

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;
}

but when I use this DLL (import) compile another DLL (say PluginA.DLL) it gives following compile errors :

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&)'

Any tips on how to use inline functions with dllexport/dllimport ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请恋爱 2025-01-02 22:59:38

我想提供一些额外的信息,因为这是一个非常棘手的问题,并且有很多关于导出/导入内联的不正确信息。

第一:内联函数可以毫无问题地与 dllimport/dllexport 一起使用。其含义非常合理:您提供了一个内联定义,该定义可以在 DLL 内部使用,也可以由客户端代码在外部使用(可以将其内联) ),但仍然可以像标准导出函数一样进行访问。换句话说,如果您需要的话,您仍然可以获得一个指向驻留在 DLL 中的函数实现的指针。例如,用例包括通过 FFI 访问函数、能够访问内存分配/释放例程(这些例程应内联在模块内,但需要使用 DLL 的 impl 来实现跨越 DLL 边界的内存等)。

请参阅https://devblogs.microsoft.com/oldnewthing/20140109-00/?p=2123 彻底处理并澄清内联和导出/导入的含义时间。

接下来,就您的具体情况而言,我认为您尝试做的事情没有立即出现问题。您希望为自己和客户提供快速、内联的向量数学,同时仍然能够像标准导出一样访问该函数。如果最后一点不正确(即,您不这样做)从来没有明确需要一个指向 DLL 函数实现的指针),那么注释/答案是正确的:删除导出/导入并使其成为 .hpp 的一部分。仅当您知道仍需要访问 DLL 的函数导出版本时,才使用导入/导出 + 内联。再说一遍,这是一件完全合理的事情,但是,它通常不是所需要的——所以请确保您确实需要它。

话虽如此,看起来您的 DLL 并未导出符号。

仔细检查以确保您在构建库时定义了 RINZOCORE_SHARED。检查 DLL 的符号并查看这些函数是否已导出(如果没有导出,并且您确信已经定义了 RINZOCORE_SHARED,那么我真的很困惑)。

检查并确保您在调用此函数的任何位置都包含具有函数定义的标头。检查并确保您的插件构建中未定义 RINZOCORE_SHARED。看起来您的插件正在尝试查找函数的导出版本,这似乎意味着它没有这些内联函数的定义

我通常仅将其与 C 链接函数一起使用,因此老实说,我不太确定 C++ ABI 方面可能会出现什么问题。

I'd like to provide some extra information since this is a very tricky issue and there's a good bit of incorrect information floating around about inline with export/import.

First: inline functions can be used with dllimport/dllexport without issue. The meaning is perfectly sensible: you provide an inline definition that can be used internally in your DLL or externally by client code (which can inline it), yet can still be accessed as though it were a standard exported function. In other words, you can still get a pointer to the implementation of the function that resides in the DLL if you need it. Use cases include, for example, accessing the function through an FFI, being able to access memory allocation/free routines that should be inlined within modules but need to use the DLL's impl for memory that crosses the DLL boundary, etc.

Please see https://devblogs.microsoft.com/oldnewthing/20140109-00/?p=2123 for a thorough treatment and clarification of what it means to be inline and exported / imported at the same time.

Next, in your specific case, I see nothing immediately wrong with what you're trying to do. You want to provide fast, inlined vector math for yourself and clients, while still being able to access that function as though it were a standard export. If that last bit isn't true (i.e., you don't ever explicitly need a pointer to the DLL's implementation of the function), then the comments/answer are correct: remove the export/import and make it part of the .hpp. Use import/export + inline only when you know that you will still require access to the DLL's exported version of the function. Again, this is a perfectly-reasonable thing, however, it's not usually what's required -- so make sure you do indeed require it.

All that being said, it looks like your DLL is not exporting the symbols.

Double-check to make sure that you're defining RINZOCORE_SHARED when you build the library. Check the DLL's symbols and see if those functions have been exported (if not, and you're positive that you've defined RINZOCORE_SHARED, then I'm really quite stumped).

Check to make sure you're including the header that has the function definitions from wherever you're calling this. Check to make sure that RINZOCORE_SHARED is NOT defined in your plugin build. It looks like your plugin is trying to find an exported version of the functions, which would seem to imply that it doesn't have the definitions of those inline functions.

I usually use this only with C-linkage functions, so I'm honestly not quite sure what all could be going wrong in terms of the C++ ABI.

椒妓 2025-01-02 22:59:38

注意:由于这是已接受的答案,因此无法删除。请认为它逻辑上被删除。欢迎您投反对票。

原始内容保留如下以供历史参考。


内联和 dllexport/dllimport 不能混合使用。

您可以

  1. 内联函数,并为使用它们的每个源文件单独编译它们;或者
  2. 将它们存储在库中,也就是说,只编译它们一次(导出它们),然后将程序的其余部分链接到该单个编译版本(导入它们)。

尝试同时做这两件事没有什么意义。

从每个具有这两者的函数定义中删除 inlineRINZO_LIB ,应该没问题。

编辑为了消除任何误解:导出和导入内联函数是可能的,事实上,只需将 dllexport/dllimport 放在声明上就可以了。

Note: since this is the accepted answer, it cannot be deleted. Please consider it logically deleted. You are welcome to downvote it.

Original content preserved below for history.


Inline and dllexport/dllimport don't mix.

You either

  1. inline your functions, and have them compiled separately for each source file that uses them; or
  2. store them in a library, that is, have them compiled just once (export them), and link the rest of the program against that single compiled version (import them).

There's little sense in trying to do both at the same time.

Remove either inline or RINZO_LIB from each function definition that have both, and you should be fine.

Edit To eliminate any misunderstanding: it is possible to export and import inline functions, and in fact simply placing a dllexport/dllimport on a declaration should just work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文