【问题标题】:cmath not found for Xcode找不到 Xcode 的 cmath
【发布时间】:2015-07-06 19:34:21
【问题描述】:

我正在使用 OpenGL ES 2 创建一个 iPhone 应用程序,它同时使用了 Objective-c 和 c++。其中有一个用于定义一些矢量属性的头文件,并且该文件包含导致错误的 cmath。

有人建议将 main.m 更改为 main.mm,但这会导致符号未找到架构错误(其中 65 个)。但是它确实摆脱了 cmath 错误。我试过摆弄各种文件的编译代码类型,但这无济于事。此外,如果我的渲染引擎中不包含 Vector.h,那么 cmath 错误就会消失,但会产生更多错误。

这已经发生在两个具有相同形式的项目上。

矢量.h

#ifndef Robots_Vector_h
#define Robots_Vector_h

#include <cmath>

const float Pi = 4 * std::atan(1.0f);
const float TwoPi = 2 * Pi;

template <typename T>
struct Vector2 {
    Vector2() {}
    Vector2(T x, T y) : x(x), y(y) {}
    T Dot(const Vector2& v) const
    {
        return x * v.x + y * v.y;
    }
    Vector2 operator+(const Vector2& v) const
    {
        return Vector2(x + v.x, y + v.y);
    }
    Vector2 operator-(const Vector2& v) const
    {
        return Vector2(x - v.x, y - v.y);
    }
    void operator+=(const Vector2& v)
    {
        *this = Vector2(x + v.x, y + v.y);
    }
    void operator-=(const Vector2& v)
    {
        *this = Vector2(x - v.x, y - v.y);
    }
    Vector2 operator/(float s) const
    {
        return Vector2(x / s, y / s);
    }
    Vector2 operator*(float s) const
    {
        return Vector2(x * s, y * s);
    }
    void operator/=(float s)
    {
        *this = Vector2(x / s, y / s);
    }
    void operator*=(float s)
    {
        *this = Vector2(x * s, y * s);
    }
    void Normalize()
    {
        float s = 1.0f / Length();
        x *= s;
        y *= s;
    }
    Vector2 Normalized() const
    {
        Vector2 v = *this;
        v.Normalize();
        return v;
    }
    T LengthSquared() const
    {
        return x * x + y * y;
    }
    T Length() const
    {
        return sqrt(LengthSquared());
    }
    const T* Pointer() const
    {
        return &x;
    }
    operator Vector2<float>() const
    {
        return Vector2<float>(x, y);
    }
    bool operator==(const Vector2& v) const
    {
        return x == v.x && y == v.y;
    }
    Vector2 Lerp(float t, const Vector2& v) const
    {
        return Vector2(x * (1 - t) + v.x * t,
                       y * (1 - t) + v.y * t);
    }
    template <typename P>
    P* Write(P* pData)
    {
        Vector2* pVector = (Vector2*) pData;
        *pVector++ = *this;
        return (P*) pVector;
    }
    T x;
    T y;
};

template <typename T>
struct Vector3 {
    Vector3() {}
    Vector3(T x, T y, T z) : x(x), y(y), z(z) {}
    T Length()
    {
        return std::sqrt(x * x + y * y + z * z);
    }
    Vector3 Cross(const Vector3& v) const
    {
        return Vector3(y * v.z - z * v.y,
                       z * v.x - x * v.z,
                       x * v.y - y * v.x);
    }
    T Dot(const Vector3& v) const
    {
        return x * v.x + y * v.y + z * v.z;
    }
    Vector3 operator+(const Vector3& v) const
    {
        return Vector3(x + v.x, y + v.y,  z + v.z);
    }
    void operator+=(const Vector3& v)
    {
        x += v.x;
        y += v.y;
        z += v.z;
    }
    void operator-=(const Vector3& v)
    {
        x -= v.x;
        y -= v.y;
        z -= v.z;
    }
    void operator/=(T s)
    {
        x /= s;
        y /= s;
        z /= s;
    }
    Vector3 operator-(const Vector3& v) const
    {
        return Vector3(x - v.x, y - v.y,  z - v.z);
    }
    Vector3 operator-() const
    {
        return Vector3(-x, -y, -z);
    }
    Vector3 operator*(T s) const
    {
        return Vector3(x * s, y * s, z * s);
    }
    Vector3 operator/(T s) const
    {
        return Vector3(x / s, y / s, z / s);
    }
    bool operator==(const Vector3& v) const
    {
        return x == v.x && y == v.y && z == v.z;
    }
    Vector3 Lerp(float t, const Vector3& v) const
    {
        return Vector3(x * (1 - t) + v.x * t,
                       y * (1 - t) + v.y * t,
                       z * (1 - t) + v.z * t);
    }
    const T* Pointer() const
    {
        return &x;
    }
    void Normalize()
    {
        if (this->Dot(*this) != 0) {
            float s = 1.0f / Length();
            x *= s;
            y *= s;
            z *= s;
        }
    }
    /*Vector3 operator=(const Vector3& v) {
     x = v.x;
     y = v.y;
     z = v.z;
     return v;
     }*/
    Vector3 Normalized() const
    {
        Vector3 v = *this;
        v.Normalize();
        return v;
    }
    template <typename P>
    P* Write(P* pData)
    {
        Vector3<T>* pVector = (Vector3<T>*) pData;
        *pVector++ = *this;
        return (P*) pVector;
    }
    T x;
    T y;
    T z;
};

template <typename T>
struct Vector4 {
    Vector4() {}
    Vector4(T xarg, T yarg, T zarg, T warg) : x(xarg), y(yarg), z(zarg), w(warg) {}
    Vector4(const Vector3<T>& v, T w) : x(v.x), y(v.y), z(v.z), w(w) {}
    T Dot(const Vector4& v) const
    {
        return x * v.x + y * v.y + z * v.z + w * v.w;
    }
    Vector4 Lerp(float t, const Vector4& v) const
    {
        return Vector4(x * (1 - t) + v.x * t,
                       y * (1 - t) + v.y * t,
                       z * (1 - t) + v.z * t,
                       w * (1 - t) + v.w * t);
    }
    void operator+=(const Vector4& v) {
        x += v.x;
        y += v.y;
        z += v.z;
        w += v.w;
    }
    Vector4 operator*(T s) {
        return Vector4(x*s, y*s, z*s, w*s);
    }
    const T* Pointer() const
    {
        return &x;
    }
    T x;
    T y;
    T z;
    T w;
};

typedef Vector2<bool> bvec2;

typedef Vector2<int> ivec2;
typedef Vector3<int> ivec3;
typedef Vector4<int> ivec4;

typedef Vector2<float> vec2;
typedef Vector3<float> vec3;
typedef Vector4<float> vec4;

#endif

RenderingEngineES2.cpp

//
//  RenderingEngineES2.cpp
//  Robots
//
//  Created by James Thorneycroft on 01/07/2015.
//  Copyright (c) 2015 James Thorneycroft. All rights reserved.
//

#include <stdio.h>

#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#include "Interfaces.h"
#include "Matrix.h"
#include <iostream>

namespace ES2 {

#define STRINGIFY(A) #A
//#include "../Shaders/Simple.frag"
//#include "../Shaders/SimpleLighting.vert"
#include "../PixelLighting.vert"
#include "../Shaders/PixelLighting.frag"


    struct UniformHandles {
        GLuint Modelview;
        GLuint Projection;
        GLuint NormalMatrix;
        GLuint LightPosition;
        GLuint CameraAxis;
    };

    struct AttributeHandle {
        GLint Position;
        GLint Normal;
        GLint Ambient;
        GLint Diffuse;
        GLint Specular;
        GLint Shininess;
    };

    struct Drawable {
        GLuint VertexBuffer;
        GLuint IndexBuffer;
        int IndexCount;
    };

    class RenderingEngine : public IRenderingEngine {
    public:
        RenderingEngine();
        void Initialize(const vector<ISurface*>& surfaces);
        void Render(const vector<Visual>& visuals) const;

    private:
        GLuint BuildProgram(const char* vertexShaderSource, const char* fragmentShaderSource) const;
        GLuint BuildShader(const char* source, GLenum shaderType) const;

        vector<Drawable> m_drawables;
        GLuint m_depthRenderBuffer;
        GLuint m_colorRenderBuffer;

        UniformHandles m_uniforms;
        AttributeHandle m_attributes;
    };

    IRenderingEngine* CreateRenderingEngine() {
        return new RenderingEngine();
    }


    GLuint RenderingEngine::BuildShader(const char* source, GLenum shaderType) const
    {
        GLuint shaderHandle = glCreateShader(shaderType);
        glShaderSource(shaderHandle, 1, &source, 0);
        glCompileShader(shaderHandle);

        GLint compileSuccess;
        glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);

        if (compileSuccess == GL_FALSE) {
            GLchar messages[256];
            glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
            std::cout << messages;
            exit(1);
        }

        return shaderHandle;
    }

    GLuint RenderingEngine::BuildProgram(const char* vertexShaderSource,
                                         const char* fragmentShaderSource) const
    {
        GLuint vertexShader = BuildShader(vertexShaderSource, GL_VERTEX_SHADER);
        GLuint fragmentShader = BuildShader(fragmentShaderSource, GL_FRAGMENT_SHADER);

        GLuint programHandle = glCreateProgram();
        glAttachShader(programHandle, vertexShader);
        glAttachShader(programHandle, fragmentShader);
        glLinkProgram(programHandle);

        GLint linkSuccess;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
        if (linkSuccess == GL_FALSE) {
            GLchar messages[256];
            glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
            std::cout << messages;
            exit(1);
        }

        return programHandle;
    }

    RenderingEngine::RenderingEngine() {
        glGenRenderbuffers(1, &m_colorRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, m_colorRenderBuffer);
    }

    void RenderingEngine::Initialize(const vector<ISurface *> &surfaces) {
        m_cameraPosition = vec4(0,0,0,0);
        vector<ISurface*>::const_iterator surface;
        for (surface = surfaces.begin(); surface != surfaces.end(); ++surface) {
            vector<float> vertices;
            (*surface)->GenerateVertices(vertices, VertexFlagNormals);
            GLuint vertexBuffer;
            glGenBuffers(1, &vertexBuffer);
            glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
            glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]), &vertices[0], GL_STATIC_DRAW);

            int indexCount = (*surface)->GetTriangleIndexCount();
            GLuint indexBuffer;
            if (!m_drawables.empty() && indexCount == m_drawables[0].IndexCount) {
                indexBuffer = m_drawables[0].IndexBuffer;
            } else {
                vector<GLushort> indices(indexCount);
                (*surface)->GenerateTriangleIndices(indices);
                glGenBuffers(1, &indexBuffer);
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
                glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLushort), &indices[0], GL_STATIC_DRAW);
            }

            Drawable drawable = { vertexBuffer, indexBuffer, indexCount };
            m_drawables.push_back(drawable);
        }

        int height, width;
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);

        glGenRenderbuffers(1, &m_depthRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderBuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);

        GLuint framebuffer;
        glGenFramebuffers(1, &framebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRenderBuffer);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, m_colorRenderBuffer);

        GLuint program = BuildProgram(PixelLightingVertexShader, PixelLightingFragmentShader);
        glUseProgram(program);

        m_attributes.Position = glGetAttribLocation(program, "Position");
        m_attributes.Normal = glGetAttribLocation(program, "Normal");
        m_attributes.Ambient = glGetUniformLocation(program, "AmbientMaterial");
        m_attributes.Diffuse = glGetAttribLocation(program, "DiffuseMaterial");
        m_attributes.Specular = glGetUniformLocation(program, "SpecularMaterial");
        m_attributes.Shininess = glGetUniformLocation(program, "Shininess");
        m_uniforms.Projection = glGetUniformLocation(program, "Projection");
        m_uniforms.Modelview = glGetUniformLocation(program, "Modelview");
        m_uniforms.NormalMatrix = glGetUniformLocation(program, "NormalMatrix");
        m_uniforms.LightPosition = glGetUniformLocation(program, "LightPosition");
        m_uniforms.CameraAxis = glGetUniformLocation(program, "CameraAxis");

        glUniform3f(m_attributes.Ambient, 0.15f, 0.15f, 0.15f);
        glUniform3f(m_attributes.Specular, 0.15f, 0.15f, 0.15f);
        glUniform1f(m_attributes.Shininess, 100.0f);

        glEnableVertexAttribArray(m_attributes.Position);
        glEnableVertexAttribArray(m_attributes.Normal);
        glEnable(GL_DEPTH_TEST);

        //m_cameraOrientation.Identity();

    }

    void RenderingEngine::Render(const vector<Visual> &visuals) const {
        glClearColor(0, 0.3f, 0.6f, 1);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        vector<Visual>::const_iterator visual = visuals.begin();
        for (int visualIndex = 0; visual != visuals.end(); ++visual, ++visualIndex) {
            ivec2 size = visual->ViewportSize;
            ivec2 lowerLeft = visual->LowerLeft;
            glViewport(lowerLeft.x, lowerLeft.y, size.x, size.y);

            mat4 rotation = visual->Orientation.ToMatrix4();
            mat4 modelView = m_cameraOrientation.ToMatrix4() * mat4::Translate(vec3(m_cameraPosition.x,m_cameraPosition.y,m_cameraPosition.z-100)) * rotation * Quaternion::CreateFromAxisAngle(vec3(-1,0,0), 1.2f).ToMatrix4();
            glUniformMatrix4fv(m_uniforms.Modelview, 1, 0, modelView.Pointer());
            vec3 camAx = m_cameraOrientation.ToMatrix3() * visual->Orientation.ToMatrix3() * Quaternion::CreateFromAxisAngle(vec3(-1,0,0), 1.2f).ToMatrix3() * vec3(0,0,1);
            glUniform3f(m_uniforms.CameraAxis, camAx.x, camAx.y, camAx.z);

            vec4 lightPosition(0, 0, 1, 0);
            glUniform3fv(m_uniforms.LightPosition, 1, (modelView*lightPosition).Pointer());

            mat3 normalMatrix = modelView.ToMat3();
            glUniformMatrix3fv(m_uniforms.NormalMatrix, 1, 0, normalMatrix.Pointer());

            float h = 4.0f * size.y / size.x;
            mat4 projectionMatrix = mat4::Frustum(-2, 2, -h / 2, h / 2, 5, 1000);
            glUniformMatrix4fv(m_uniforms.Projection, 1, 0, projectionMatrix.Pointer());

            vec3 color = visual->Color * 0.75f;
            glVertexAttrib4f(m_attributes.Diffuse, color.x, color.y, color.z, 1);

            int stride = 2*sizeof(vec3);
            const GLvoid* offset = (const GLvoid*) sizeof(vec3);
            GLint position = m_attributes.Position;
            GLint normal = m_attributes.Normal;
            const Drawable& drawable = m_drawables[visualIndex];
            glBindBuffer(GL_ARRAY_BUFFER, drawable.VertexBuffer);
            glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, stride, 0);
            glVertexAttribPointer(normal, 3, GL_FLOAT, GL_FALSE, stride, offset);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drawable.IndexBuffer);
            glDrawElements(GL_TRIANGLES, drawable.IndexCount, GL_UNSIGNED_SHORT, 0);
        }
    }
}

【问题讨论】:

  • 正确的做法是按照“某人”的说法,使用 .mm 作为文件扩展名。之后您收到的架构错误几乎肯定是因为编译 succeeded 和链接 failed (这完全是一个不同的问题,可能是因为您没有配置工具包'正在尝试正确使用或未准备好与 iPhone 兼容的框架)。
  • @WhozCraig 从以前的项目中复制了代码,所以我忘了链接库。很奇怪这个问题现在才出现,但是非常感谢您的快速和正确的回答。

标签: c++ ios opengl-es xcode6 file-not-found


【解决方案1】:

代替

#include <cmath>

使用

#include <math.h>

【讨论】:

    【解决方案2】:

    这里的问题是,Objective-C 在 C API 之上工作,而 &lt;cmath&gt; 在 C 中不可用 - &lt;cmath&gt; 是 C++ 包含,C 等价物是 &lt;math.h&gt; (如@MrTweek pointed out).

    解决方案是切换到使用 Objective-C++,它在 C++ 之上运行,让您可以访问 Obj-C 类中的所有 C++ 功能,以及让您导入 C++ 标头(例如您的)。

    将您的 Objective-C 代码切换到 Objective-C++ 很简单——只需将任何具有所需 #include "Vector.h" 的 Objective-C 实现文件重命名为具有 .mm 扩展名而不是 .m _(例如 MyRendererView.m 是重命名为MyRendererView.mmMyRendererView.h 可以保持原样)。 就是这样! 您现有的所有 Objective-C 代码都可以轻松使用您的 Objective-C++ 类;您只需要更改 Objective-C 文件的扩展名,包括您的 Vector.h 或公开 C++ 类型自己的标头。

    在使用 Objective-C++ 而不是 Objective-C 时,有一些小的命名警告,我已经记不清了。如果您遇到任何奇怪的错误,那几乎可以肯定是 StackOverflow 的解决方法。它可能归结为调整 Xcode 构建设置——最重要的构建设置是“C 语言方言”和“C++ 语言方言”设置。

    【讨论】:

    • 如果是预编译的头文件呢?
    • @zwcloud PCH 文件通常应该被 C 和 C++ 包含 (如果项目同时包含 C 和 C++ 代码;只有 C 或只有 C++ 的项目可能不包含两者都写)。较旧的 Xcode 生成的 PCHe 将包括条件编译,例如 #ifdef __cplusplus extern "C" { #endif;我不确定 Xcode 是否仍然添加它,但如果没有,您可以自己添加它。使您的 PCH 同时兼容 C 和 C++(使用 extern 和其他模式)的过程在其他方面都有很好的记录,并且不特定于 Objective-C、Xcode 或 macOS 开发。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 2021-11-02
    相关资源
    最近更新 更多