Xcode: Wrong file extension can cause STL errors

Xcode relies on the file extension to figure out if a module should be interpreted as C, C++, Objective-C or Objective-C++. These extensions are, respectively: .c, .cpp, .m, .mm. Xcode also looks at a per-file project setting, which can be accessed from the IDE by selecting the file and pressing Command-I (Get Info). The setting is under General/File Type. The project setting overrides the type that is derived from the file name.

A problem arises when using precompiled headers. Since in Xcode precompiled headers are compiled directly from the header file, rather than a source module that includes the header, it can get confused as to which language needs to be used.

I have a project that was compiling fine when it wasn't using precompiled headers. This project has a common header file (common.h) which includes several STL classes: <vector>, <list>, <algorithm>, etc. The files that use this header (including some Objective-C++ files) were all set up correctly: they were either .cpp or .mm. When I set it up to use precompiled headers, I got the following errors:


error: vector: No such file or directory
error: list: No such file or directory
error: algorithm: No such file or directory
error: map: No such file or directory
error: string: No such file or directory
error: parse error before 'namespace'
warning: data definition has no type or storage class


Why would the error happen only when I turn on precompiled headers?

The problem turned out to be the main project file (main.m). It looks like Xcode looks at your main entry module (main.m or main.mm) in order to find out which language to use to compile your precompiled header.

Renaming main.m to main.mm fixed it.

Rendering to pixel buffer in Mac OS X

This article presents an example of rendering to pixel buffer in Mac OS X using OpenGL. Rendering to pixel buffer is sometimes referred to as off-screen rendering or rendering to texture, although the result is not always used as a texture.

If your objective is either to render to a texture and then use this texture, or to render to an offscreen area of memory and use the rendered pixels (for example as a heightmap), there are two ways to achieve it:
  • Render to the backbuffer, copy the data from the backbuffer and continue your rendering;
  • Render to a pixel buffer, which is a separate frame buffer that never gets swapped with the front buffer.
The first approach is easier and requires less setup. However, it doesn't work very well in Mac OS, due to the fact that the Mac OS window manager, Quartz Compositor, is a compositing window manager. This means the window manager may pick up your back buffer for rendering at any time. It accesses the back buffer asynchronously. If you draw a temporary texture or image into the back buffer, it may be displayed, even if you don't intend to swap it to the front buffer. This is noticed if the user moves the window, especially if the window is made to overlap other objects like the Dock.

Therefore, the more correct approach is to render to a pixel buffer, or PBuffer. Rendering to a pixel buffer in Mac OS X can be tricky, due to the fact that you have to create a pixel format, a context and a pixel buffer, and manage them. In order to make the process easier, a class can be created which wraps these operations.

PixelBuffer.h



/*
* PixelBuffer.h
*
* Created by Eduardo Poyart on 2/24/08.
*
*/

struct PixelBufferData;

class PixelBuffer
{
protected:
PixelBufferData* m_data;

public:
PixelBuffer();
~PixelBuffer();

void init(int width, int height, unsigned long target,
unsigned long internalFormat, long max_level);

int begin_pbuffer(GLenum face, GLint level);
int end_pbuffer();
};

PixelBuffer.cpp



/*
* PixelBuffer.cpp
*
* Created by Eduardo Poyart on 2/24/08.
*
*/

#include <Carbon/Carbon.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>

#include "PixelBuffer.h"

#include <assert.h>

void check_result(int result)
{
if (result != 0)
{
fprintf(stderr, "CGL error: %d - %s\n", result, CGLErrorString((CGLError)result));
}
}

struct PixelBufferData
{
CGLPBufferObj m_pbuffer;
CGLContextObj m_context;
CGLContextObj m_prev_context;

PixelBufferData(int width, int height, unsigned long target,
unsigned long internalFormat, long max_level);
~PixelBufferData();
};

PixelBufferData::PixelBufferData(int width, int height, unsigned long target,
unsigned long internalFormat, long max_level)
{
CGLError result = CGLCreatePBuffer(width, height, target, internalFormat, max_level, &m_pbuffer);
check_result(result);

CGLPixelFormatObj pix;

CGLPixelFormatAttribute attrs[] = {
kCGLPFANoRecovery,
kCGLPFAColorSize, (CGLPixelFormatAttribute)24,
kCGLPFADepthSize, (CGLPixelFormatAttribute)16,
kCGLPFAAccelerated,
(CGLPixelFormatAttribute)0
};

GLint npix;
result = CGLChoosePixelFormat(attrs, &pix, &npix);
check_result(result);

result = CGLCreateContext(pix, NULL, &m_context);
check_result(result);
result = CGLDestroyPixelFormat(pix);
check_result(result);
}

PixelBufferData::~PixelBufferData()
{
CGLError result = CGLDestroyPBuffer(m_pbuffer);
check_result(result);
result = CGLDestroyContext(m_context);
check_result(result);
}

PixelBuffer::PixelBuffer(): m_data(NULL) {}

void PixelBuffer::init(int width, int height, unsigned long target,
unsigned long internalFormat, long max_level)
{
assert(m_data == NULL);
m_data = new PixelBufferData(width, height, target, internalFormat, max_level);
}

PixelBuffer::~PixelBuffer() { delete m_data; }

int PixelBuffer::begin_pbuffer(GLenum face, GLint level)
{
m_data->m_prev_context = CGLGetCurrentContext();
CGLError result = CGLSetCurrentContext(m_data->m_context);
check_result(result);

long screen;
result = CGLGetVirtualScreen(m_data->m_prev_context, &screen);
check_result(result);
result = CGLSetPBuffer(m_data->m_context, m_data->m_pbuffer,
face, level, screen);
check_result(result);
return (int)result;
}

int PixelBuffer::end_pbuffer()
{
CGLError result = CGLSetCurrentContext(m_data->m_prev_context);
check_result(result);
return (int)result;
}

Notes:


  1. The PixelBuffer class is set up in a way that it's easy to make it cross-platform. The header file doesn't reference anything Mac OS specific. The PixelBufferData is opaque to the external viewer. In the header file, it is defined solely as a pointer, and all of the platform-specific code is in the cpp file. The CPP file can be made cross-platform by means of #ifdefs, or it can be swapped entirely, while the interface is kept clean and consistent.
  2. The PixelBufferData constructor builds a CGLPixelFormatObj object, which may be customized for specific purposes (change in pixel format, depth buffer, etc). It can also be made to receive these parameters and pass them to the pixel format object.
  3. The construct guarantees that you never leak memory from PixelBufferData objects. The proof is left for the reader.

An usage example:



class MyApplication
{
protected:
PixelBuffer m_pbuffer;
public:
void init(int width, int height)
{
m_pbuffer.init(m_width, m_height, GL_TEXTURE_2D, GL_RGBA, 0);
(...)
}

void render()
{
m_pbuffer.begin_pbuffer(0, 0);

// OpenGL scene setup
(...)

// OpenGL render
(...)

// Read pixel buffer to memory (m_heightmap)
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_heightmap);

// Or, read pixel buffer to texture
glGenTextures(1, &m_texturenumber);
glBindTexture(GL_TEXTURE_2D, m_texturenumber);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 64, 64, 0);

// End working with pixel buffer
m_pbuffer.end_pbuffer();

// From now on, more OpenGL commands can be issued and they will go to the main buffer.
(...)
}
}