0

MSVC 2008 で静的ライブラリ Win32 (実際には Win32 コードは含まれていません) ライブラリを作成しましたが、現在 QT Creator でリンクしようとしています。しかし、コンパイルするたびにエラーが発生します。

C:\Users\Snowball\Documents\QT Creator\Libraries\FontSystem\main.cpp:-1: error: undefined reference to `NGUI::CFont::CFont()'

このライブラリは、FreeImage を使用して PNG をロードし、それを個々のシンボルに「カット」してからイメージ データを渡し、そのイメージ データからgluBuild2DMipMaps()OpenGL テクスチャを作成して、後で文字列を描画するときに使用するフォント システムです。すべてのクラス メソッドが定義されており、クラス全体が という名前空間の一部ですNGUI。これにより、何らかの理由で 2 つのフォント システムが使用されている場合でも、フォント システムが別のシステムと混同されることはありません。このライブラリをリンクするには、次のコードを .pro ファイルに追加するだけです。LIBS += FontSystem.lib

現在、アプリケーション内の唯一のファイルは次のとおりです。

#include "fontsystem.h"
using namespace NGUI;

int main(int argc, char *argv[])
{
    cout<< "Starting the FontSystem..."<< endl;

    CFont *cFont = new CFont();
    cout<< "FontSystem Started!"<< endl;

    system("sleep 1");
    return 0;
}

ファイル fontsystem.h は次のようになります。

#ifndef FONTSYSTEM_H
#define FONTSYSTEM_H

// Include the Basic C++ headers.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <assert.h>
#include <limits>
using namespace std;

// Include the OpenGL and Image Headers.
#include <GL/gl.h>
#include <GL/glu.h>
#include "utilities.h"

// Macros.
#define DIM(x) (sizeof(x)/sizeof(*(x)))

/*
    The Font System works by loading all the font images (max image size 32px^2) into memory and storing
  the OpenGL texture ID's into an array that can be access at all times. The DrawString() functions will
  search through the string for the specified character requested to draw and then it will draw a quad
  and paint the texture on it. Since all the images are pre-loaded, no loading of the images at load time
  is necessary, this is memory consuming but efficiant for the CPU. ALL functions WILL return a character
  string specifing errors or success. A function will work as long as it can and when an error happens,
  unless the error is fatal, the functions will NOT rollback changes! This ensures that during testing, a
  very certain bug can be spotted.
*/

namespace NGUI // This namespace is used to ensure no confusion happens. This font system paints 2D fonts for GUIs.
{
    class CFont
    {
    public:
        CFont();
        ~CFont();

        template<typename tChar> char* DrawString(tChar *apString, int aiSize, int aiX, int aiY);
        template<typename tNum> char* DrawString(tNum anNumber, int aiSize, int aiX, int aiY);

    private:
        char* SetupFont(); // This function will load as many images as possible into memory.

        GLuint miTextIDs[36];
        int miDrawIDs[1024];
    };
}

#endif // FONTSYSTEM_H

編集: fontsystem.h の実装ファイルは次のとおりです。

    #include "fontsystem.h"

#include "fontsystem.h"

namespace NGUI
{
    CFont::CFont()
    {
        SetupFont();
    }

    CFont::~CFont() {}

    template<typename tChar>
    char* CFont::DrawString(tChar *apString, int aiSize, int aiX, int aiY)
    {
        // Search the string from most significant character to least significant.
        int iSelectIndex = 0;
        for(size_t i = 0; apString[i] != NULL; ++i)
        {
            iSelectIndex = apString[i] >= '0' && apString[i] <= '9' ? (apString[i] - '0') :
                           apString[i] >= 'A' && apString[i] <= 'Z' ? (apString[i] - 'A' + 10) :
                           apString[i] >= 'a' && apString[i] <= 'z' ? (apString[i] - 'a' + 10) :
                           apString[i] == ' ' ? 36 : // This is a special case, This see's if the current character is a space or not.
                           -1;

            if(iSelectIndex == -1)
            {
                return "The String Is Corrupt! Aborting!";
            }

            // Add the current selected character to the drawing array.
            miDrawIDs[i] = iSelectIndex;
        }

        // Go through and draw each and every character.
        for(size_t i = 0; i < DIM(miDrawIDs); ++i)
        {
            // Paint each qaud with the X,Y coordinates. After each quad has been successfully drawn,
            // Add the size to the X coordinate. NOTE: Each character is square!!!

            if(miDrawIDs[i] != 36)
            {
                glBindTexture(GL_TEXTURE_2D, miDrawIDs[i]);
            }

            // The font color is always white.
            glColor4f(1.0, 1.0, 1.0, 0.0); // The alpha argument in the function call is set to 0 to allow color only where image data is present.

            glBegin(GL_QUADS);
                glTexCoord2i(0, 0);
                glVertex2i(aiX, aiY);

                glTexCoord2i(1, 0);
                glVertex2i(aiX + aiSize, aiY);

                glTexCoord2i(1, 1);
                glVertex2i(aiX + aiSize, aiY + aiSize);

                glTexCoord2i(0, 1);
                glVertex2i(aiX, aiY + aiSize);
            glEnd();

            // Now, increase the X position by the size.
            aiX += aiSize;
        }

        return "Successful Drawing of String!";
    }

    template<typename tNum>
    char* CFont::DrawString(tNum anNumber, int aiSize, int aiX, int aiY)
    {
        // Convert the supplied number to a character string via snprintf().
        char *vTempString = new char[1024];
        snprintf(vTempString, 1024, "%f", anNumber);

        // Next, run DrawString().
        return DrawString<char>(vTempString, aiSize, aiX, aiY);
    }

    char* CFont::SetupFont()
    {
        // First Load The PNG file holding the font.
        FreeImage_Initialise(false);

        FIBITMAP *spBitmap = FreeImage_Load(FIF_PNG, "Font.png", BMP_DEFAULT);

        if(!spBitmap)
        {
            return "Was Unable To Open/Decode Bitmap!";
        }

        // Do an image sanity check.
        if(!FreeImage_HasPixels(spBitmap))
        {
            return "The Image doesn't contain any pixel data! Aborting!";
        }

        // The Image will have the red and blue channel reversed, so we need to correct them.
        SwapRedBlue32(spBitmap);

        // Retrieve all the image data from FreeImage.
        unsigned char *pData = FreeImage_GetBits(spBitmap);
        int iWidth = FreeImage_GetWidth(spBitmap);

        // Cutup the PNG.
        int iFontElementSize = (32*32)*4; // The first two numbers, are the dimensions fo the element, the last number (4) is the number of color channels (Red Green Blue and Alpha)
        bool bDone = false; // This bit is only set when the entire image has been loaded.
        unsigned char *pElemBuff = new unsigned char[iFontElementSize]; // The temporary element buffer.
        int iDataSeek = 4; // Start with an offset of 4 because the first byte of image data starts there.
        int iTexIdx = 0; // This is an offset specifing which texture to create/bind to.

        // Create all 36 OpenGL texures. 0-9 and A-Z and finally space (' ')
        glGenTextures(37, miTextIDs);

        while(!bDone)
        {
            // Now load the an element into the buffer.
            for(int i = 0, iXCount = 0, iYCount = 0;
                i < iFontElementSize; ++i, ++iXCount)
            {
                if(iXCount >= (32*4))
                {
                    iXCount = 0; // Reset the column offset.
                    ++iYCount; // Move down 1 row.
                    iDataSeek += ((iWidth * 4) - (32*4)); // Set the data seek to the next corrosponding piece of image data.
                }

                if(pData[iDataSeek] == NULL)
                {
                    break;
                }

                pElemBuff[i] = pData[iDataSeek];
            }

            // Check to see if we are done loading to prevent memory corruption and leakage.
            if(bDone || iTexIdx >= 37)
            {
                break;
            }

            // Create The OpenGL Texture with the current Element.
            glBindTexture(GL_TEXTURE_2D, miTextIDs[iTexIdx]);
            gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, 32, 32, GL_RGBA, GL_UNSIGNED_BYTE, pElemBuff);

            // Create the correct texture envirnment to the current texture.
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        }

        // Do a little house cleaning!
        delete[] pElemBuff;
        delete pData;
        FreeImage_Unload(spBitmap);
        FreeImage_DeInitialise();
    }
}

注意: このコードはまだテストされていませんが、問題なくコンパイルされます (MSVC 2008 によると)。

system("sleep 1");toを変更するのを忘れてsystem("PAUSE");いました。そのコマンドを呼び出す理由は、もともとこれを Linux でビルドしていたためです。

編集 2: ファイルを反映するように実装コードを更新しました。

4

0 に答える 0