views:

65

answers:

1

Hello all, I am trying to write a debug class for a project I am working on, and I do not want to have to pass a debug object around so I was trying to do it this way. However, I do not know why my compiler or linker seems to be skipping the implementation I am writing for it.

If I add #include "Debug.cpp" to main.cpp this code works just fine. The compiler is somehow missing the implementation of the open, close, and print functions unless I either put the implementation in the .h file or #include Debug.cpp.

Do you have any idea why it is not seeing the implementation in Debug.cpp?

I do not think it matters, but currently debug.h and debug.cpp are in one project and main.cpp is in another project (both within the same solution however, visual studio 2008). main.cpp is being built as an executable, and debug.h and debug.cpp are being compiled as a dynamic library (dll).

Debug.h

Code: Select all

#define BUFFER_SIZE 1028
#include <string>
#include <fstream>
#include <assert.h>
#include <stdarg.h> // va_arg

#ifndef _DEBUG_H_
#define _DEBUG_H_
namespace Debugger
{
   // member variables
   extern const unsigned int m_sizebuffer;
   extern std::ofstream m_file;
   extern bool m_fileopened;
   extern char m_buffer[BUFFER_SIZE];
   extern va_list m_vl;

   /*
      'extern' keyword there to remind myself that
      all functions are implicitly extern, so
      declaring variables with 'extern' is more intuitive.
      Will remove when the 'extern' keyword becomes second nature to me.
   */
   extern void open_file();
   extern void close_file();
   extern void print(const char* fmt, ...);
}

#endif

Debug.cpp

Code: Select all

#ifndef _DEBUG_H_
#include "Debug.h"
#endif

namespace Debugger
{
   const unsigned int m_sizebuffer = BUFFER_SIZE;
   std::ofstream m_file;
   bool m_fileopened;
   char m_buffer[BUFFER_SIZE];
   va_list m_vl;

   void Debugger::open_file()
   {
      // file cannot already be opened.
      assert(!m_fileopened);
      m_file.clear(); // clear contents of debug file.

      //if directory already exists nothing *SHOULD* happen. platform dependent.
      system("mkdir Data");

      m_file.open("./Data/ErrorLog.txt");   // hard-coding filename is intentional
      if(m_file.is_open() )
      {
         m_fileopened = true;
         print("Debug: successfully loaded file './Data/ErrorLog.txt' \n" );
      }
   }

   void Debugger::close_file()
   {
      if(m_fileopened)
      {
         m_file.close();
         m_fileopened = false;
      }
   }

   /*
      WARNING: Should only accept c-style strings only. If output is ever cryptic double check
      that we are not passing c++ Strings instead of char*, do not know how to differentiate if
      fmt is a c-style string (char*) or a C++ String.
   */
   void Debugger::print(const char* fmt, ...)
   {
      if(!m_fileopened)
      {
         open_file();
         print("Debug file opened. \n");
      }
      int retval = 0;

      va_start(m_vl, fmt);
      retval = vsnprintf_s(m_buffer, m_sizebuffer, m_sizebuffer, fmt, m_vl);
      va_end(m_vl);
      m_file << m_buffer;
      m_file.flush();

      assert(retval > 0);
   }
}

main.cpp

Code: Select all

#include "stdlib.h"
#ifndef _DEBUG_H_
#include "Debug.h"
#endif

int main(int argc, char* argv[])
{
   //Debugger::print("this should work~! yay");

   return EXIT_SUCCESS;
}

If I un-comment the print line in the main function I get the following error:

Code: Select all

1>LINK : C:\Users\Benjamin\Desktop\vs projects (c++)\Game Debugger\debug class\Debug\Smashteroids.exe not found or not built by the last incremental link; performing full link
1>main.obj : error LNK2019: unresolved external symbol "void __cdecl Debugger::print(char const *,...)" (?print@Debugger@@YAXPBDZZ) referenced in function _main
1>C:\Users\Benjamin\Desktop\vs projects (c++)\Game Debugger\debug class\Debug\Smashteroids.exe : fatal error LNK1120: 1 unresolved externals

edit: A link to my original discussion:

http://elysianshadows.com/phpBB3/viewtopic.php?f=6&amp;t=5328&amp;start=999999

A: 

In Debug.cpp I believe you have extra Debugger:: qualifiers on your function names. Try for example void print(const char* fmt, ...) in the cpp file instead. The function is already enclosed in the Debugger namespace there and need not be qualified again.

EDIT: Did you actually link Debug.o into the final executable? If you don't link in all the object files into your binary, you'll get linker errors like this. Unlike runtimes like Java, C++ is unable to magically determine from where to get a definition for functions such as print. You have to explicitly tell it by linking in all the respective files.

Mark B
I tried this, the extra qualifier does not seem to matter as I get the same error with or without it.
Ben Adamson
"Did you actually link Debug.o into the final executable?"No, I did not. At-least not on purpose. I don't know how to do this, I need to link an object file?
Ben Adamson