结合使用内联数学库和预编译头文件时出现链接错误

发布于 2024-11-17 05:49:47 字数 2409 浏览 4 评论 0原文

我今天遇到了一个相当奇怪的问题。我有一个针对 SSE 优化的数学库,因此几乎所有功能都被声明为内联。为了简化起见,我将仅使用一个类 Vector3 来解释问题:

Vector3 在 Vector3.h 中声明,如下所示:

#ifndef VIRTUS_VECTOR3_H
#define VIRTUS_VECTOR3_H

#ifndef VEC3INLINE
  #if(_DEBUG)
    #define VEC3INLINE inline
  #else
    #define VEC3INLINE __forceinline
  #endif
#endif

namespace Virtus {

struct Vector3
{
  union
  {
    struct { f32 x,y,z; };
    f32 v[3];
  };

  Vector3(void);
  Vector3(const Vector3& rhs);
  Vector3(f32 xx, f32 yy, f32 zz);

  VEC3INLINE Vector3& operator=(const Vector3& rhs);

  VEC3INLINE Vector3 operator+(f32 rhs) const;
  VEC3INLINE Vector3 operator-(f32 rhs) const;
  VEC3INLINE Vector3 operator*(f32 rhs) const;
  VEC3INLINE Vector3 operator/(f32 rhs) const;
  VEC3INLINE Vector3& operator+=(f32 rhs);
  VEC3INLINE Vector3& operator-=(f32 rhs);
...

#include "vector3.inl"
#endif

在 vector3.inl 中,我继续定义所有函数

namespace Virtus {

Vector3::Vector3(void)
  : x(0.0f), y(0.0f), z(0.0f)
{
}

Vector3::Vector3(const Vector3& rhs)
  : x(rhs.x), y(rhs.y), z(rhs.z)
{
}

Vector3::Vector3(f32 xx, f32 yy, f32 zz)
  : x(xx), y(yy), z(zz)
{
    }

VEC3INLINE Vector3& Vector3::operator=(const Vector3& rhs)
{
  memcpy(v, rhs.v, sizeof(v));
  return *this;
}

    ...

,然后将所有数学对象包含在一个文件中名为 math.h

#ifndef VIRTUS_MATH_H
#define VIRTUS_MATH_H

#include "vector2.h"
#include "vector3.h"
#include "vector4.h"
#include "matrix4.h"
#include "primesearch.h"

namespace Virtus
{
  class MathException
  {
  public:
    enum ErrorCode
    {
      PRIME_SEARCH_INVALID_ELEMENTS,
      PRIME_SEARCH_UNSUFFNUM_PRIMES
    };

    MathException(ErrorCode code) : m_Error(code) {}
    ErrorCode What(void) const { return m_Error; }

  private:
    ErrorCode m_Error;
  };
} // namespace virtus

#endif // Include Guard

的文件包含在我的预编译头文件(precompiled.h 又名 stdafx.h)中。

我使用 Visual Studio 2008,它会自动从构建过程中排除 .inl 文件。

这是我收到的链接器错误:

错误 1 ​​错误 LNK2005:“公共: __thiscall Virtus::Vector3::Vector3(void)" (??0Vector3@Virtus@@QAE@XZ) 已经 定义于 precompiled.obj main.obj Virtus

我尝试了几乎所有可以想象到的方法来修复这个问题,比如手动从构建中排除所有 inl 文件;不将 math.h 包含在预编译文件中,但只包含在我需要的地方(在这种情况下,我会得到类似的已定义链接器错误);从 inl 扩展名更改为 cpp 扩展名等。我能够修复它的唯一方法是使用 #pragma 一次而不是包含防护。所以我现在最好的猜测是它与预编译头文件和包含防护的组合有关,但我不太确定如何解决这个问题。

非常感谢您的帮助!

I came about a rather weird problem today. I have a math library optimized for SSE, therefore almost all functionality is declared as inline. For simplification purposes I will only explain the problem using one class, Vector3:

Vector3 is declared in Vector3.h, something like this:

#ifndef VIRTUS_VECTOR3_H
#define VIRTUS_VECTOR3_H

#ifndef VEC3INLINE
  #if(_DEBUG)
    #define VEC3INLINE inline
  #else
    #define VEC3INLINE __forceinline
  #endif
#endif

namespace Virtus {

struct Vector3
{
  union
  {
    struct { f32 x,y,z; };
    f32 v[3];
  };

  Vector3(void);
  Vector3(const Vector3& rhs);
  Vector3(f32 xx, f32 yy, f32 zz);

  VEC3INLINE Vector3& operator=(const Vector3& rhs);

  VEC3INLINE Vector3 operator+(f32 rhs) const;
  VEC3INLINE Vector3 operator-(f32 rhs) const;
  VEC3INLINE Vector3 operator*(f32 rhs) const;
  VEC3INLINE Vector3 operator/(f32 rhs) const;
  VEC3INLINE Vector3& operator+=(f32 rhs);
  VEC3INLINE Vector3& operator-=(f32 rhs);
...

#include "vector3.inl"
#endif

In vector3.inl I proceed with defining all of the functions

namespace Virtus {

Vector3::Vector3(void)
  : x(0.0f), y(0.0f), z(0.0f)
{
}

Vector3::Vector3(const Vector3& rhs)
  : x(rhs.x), y(rhs.y), z(rhs.z)
{
}

Vector3::Vector3(f32 xx, f32 yy, f32 zz)
  : x(xx), y(yy), z(zz)
{
    }

VEC3INLINE Vector3& Vector3::operator=(const Vector3& rhs)
{
  memcpy(v, rhs.v, sizeof(v));
  return *this;
}

    ...

I then include all of my math objects in a file called math.h

#ifndef VIRTUS_MATH_H
#define VIRTUS_MATH_H

#include "vector2.h"
#include "vector3.h"
#include "vector4.h"
#include "matrix4.h"
#include "primesearch.h"

namespace Virtus
{
  class MathException
  {
  public:
    enum ErrorCode
    {
      PRIME_SEARCH_INVALID_ELEMENTS,
      PRIME_SEARCH_UNSUFFNUM_PRIMES
    };

    MathException(ErrorCode code) : m_Error(code) {}
    ErrorCode What(void) const { return m_Error; }

  private:
    ErrorCode m_Error;
  };
} // namespace virtus

#endif // Include Guard

and math.h is included in my precompiled header file (precompiled.h aka stdafx.h)

I use Visual Studio 2008, which should automatically exclude .inl files from the build process.

This is the linker error I am getting:

Error 1 error LNK2005: "public:
__thiscall Virtus::Vector3::Vector3(void)"
(??0Vector3@Virtus@@QAE@XZ) already
defined in
precompiled.obj main.obj Virtus

I tried fixing this pretty much every way imaginable, like excluding all inl files from the build manually; not including math.h in the precompiled file but only where I need it ( in which case I get a similar already defined linker error); changing from the inl extension to cpp extension, and so on. The only way I was able to fix it was using #pragma once instead of include guards. So my best guess at this time is that it has something to do with the combination of precompiled header files and include guards, but I'm not really sure how to fix this.

Help would be much appreciated!

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

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

发布评论

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

评论(1

落叶缤纷 2024-11-24 05:49:47

vector3.inl 中的每个定义都需要使用 inline 显式定义。

Each of the definitions inside vector3.inl needs to be explicitly defined with inline.

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