Hello I'm getting these 2 LNK errors and haven't been able to figure out how to resolve them, any help is greatly appreciated! Its was an empty Win32 Application that i created and added code into from existing source.

Error	1	error LNK2019: unresolved external symbol __imp__timeGetTime@0 referenced in function "public: __thiscall Engine::Engine(struct EngineSetup *)" (??0Engine@@QAE@PAUEngineSetup@@@Z)	~(path)\Engine.obj
Error	2	error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup	~(path)\MSVCRTD.lib(crtexew.obj)

- Argo

The first error indicates that you have called a time functon that does not exist. Read this thread for the solution to that problem.

The second error is quite simple. You created a MS-Windows project but you probably replaced WinMain() with main(). If you wanted main() then you should have created a console project.

Edited 5 Years Ago by Ancient Dragon: n/a

The first error indicates that you have called a time functon that does not exist. Read this thread for the solution to that problem.

The second error is quite simple. You created a MS-Windows project but you probably replaced WinMain() with main(). If you wanted main() then you should have created a console project.

I noticed I forgot to make another project that included the main, so I have added a main in now but I'm getting errors when I try to create the engine and then run it. Anyone know what would be causing this?

Main.obj : error LNK2001: unresolved external symbol "public: void __thiscall Engine::Run(void)" (?Run@Engine@@QAEXXZ
Main.obj : error LNK2001: unresolved external symbol "class Engine * g_engine" (?g_engine@@3PAVEngine@@A)
Main.obj : error LNK2001: unresolved external symbol "public: __thiscall Engine::Engine(struct EngineSetup *)" (??0Engine@@QAE@PAUEngineSetup@@@Z)
#include "Engine.h"

//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
Engine *g_engine = NULL;

//-----------------------------------------------------------------------------
// Handles Windows messages.
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
	switch( msg )
	{
		case WM_ACTIVATEAPP:
			g_engine->SetDeactiveFlag( !wparam );
			return 0;

		case WM_DESTROY:
			PostQuitMessage( 0 );
			return 0;

		default:
			return DefWindowProc( wnd, msg, wparam, lparam );
	}
}

//-----------------------------------------------------------------------------
// The engine class constructor.
//-----------------------------------------------------------------------------
Engine::Engine( EngineSetup *setup )
{
	// Indicate that the engine is not yet loaded.
	m_loaded = false;

	// If no setup structure was passed in, then create a default one.
	// Otehrwise, make a copy of the passed in structure.
	m_setup = new EngineSetup;
	if( setup != NULL )
		memcpy( m_setup, setup, sizeof( EngineSetup ) );

	// Store a pointer to the engine in a global variable for easy access.
	g_engine = this;

	// Prepare and register the window class.
	WNDCLASSEX wcex;
	wcex.cbSize        = sizeof( WNDCLASSEX );
	wcex.style         = CS_CLASSDC;
	wcex.lpfnWndProc   = WindowProc;
	wcex.cbClsExtra    = 0;
	wcex.cbWndExtra    = 0;
	wcex.hInstance     = m_setup->instance;
	wcex.hIcon         = LoadIcon( NULL, IDI_APPLICATION );
	wcex.hCursor       = LoadCursor( NULL, IDC_ARROW );
	wcex.hbrBackground = NULL;
	wcex.lpszMenuName  = NULL;
	wcex.lpszClassName = setup->name;
	wcex.hIconSm       = LoadIcon( NULL, IDI_APPLICATION );
	RegisterClassEx( &wcex );

	// Initialise the COM using multithreaded concurrency.
	CoInitializeEx( NULL, COINIT_MULTITHREADED );

	// Create the window and retrieve a handle to it.
	// Note: Later the window will be created using a windowed/fullscreen flag.
	m_window = CreateWindow( L"WindowClass", m_setup->name, WS_OVERLAPPED, 0, 0, 800, 600, NULL, NULL, m_setup->instance, NULL );

	// Seed the random number generator with the current time.
	srand( timeGetTime() );

	// The engine is fully loaded and ready to go.
	m_loaded = true;
}

//-----------------------------------------------------------------------------
// The engine class destructor.
//-----------------------------------------------------------------------------
Engine::~Engine()
{
	// Ensure the engine is loaded.
	if( m_loaded == true )
	{
		// Everything will be destroyed here (such as the DirectX components).
	}

	// Uninitialise the COM.
	CoUninitialize();

	// Unregister the window class.
	UnregisterClass( L"WindowClass", m_setup->instance );

	// Destroy the engine setup structure.
	SAFE_DELETE( m_setup );
}

//-----------------------------------------------------------------------------
// Enters the engine into the main processing loop.
//-----------------------------------------------------------------------------
void Engine::Run()
{
	// Ensure the engine is loaded.
	if( m_loaded == true )
	{
		// Show the window.
		ShowWindow( m_window, SW_NORMAL );

		// Enter the message loop.
		MSG msg;
		ZeroMemory( &msg, sizeof( MSG ) );
		while( msg.message != WM_QUIT )
		{
			if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
			else if( !m_deactive )
			{
				// Calculate the elapsed time.
				unsigned long currentTime = timeGetTime();
				static unsigned long lastTime = currentTime;
				float elapsed = ( currentTime - lastTime ) / 1000.0f;
				lastTime = currentTime;
			}
		}
	}

	// Destroy the engine.
	SAFE_DELETE( g_engine );
}

//-----------------------------------------------------------------------------
// Returns the window handle.
//-----------------------------------------------------------------------------
HWND Engine::GetWindow()
{
	return m_window;
}

//-----------------------------------------------------------------------------
// Sets the deactive flag.
//-----------------------------------------------------------------------------
void Engine::SetDeactiveFlag( bool deactive )
{
	m_deactive = deactive;
}
#ifndef ENGINE_H
#define ENGINE_H

//-----------------------------------------------------------------------------
// DirectInput Version Define
//-----------------------------------------------------------------------------
#define DIRECTINPUT_VERSION 0x0800

//-----------------------------------------------------------------------------
// System Includes
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <tchar.h>
#include <windowsx.h>

//-----------------------------------------------------------------------------
// DirectX Includes
//-----------------------------------------------------------------------------
#include <d3dx9.h>
#include <dinput.h>
//#include <dplay8.h>
//#include <dmusici.h>  ------- outdated

//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define SAFE_DELETE( p )       { if( p ) { delete ( p );     ( p ) = NULL; } }
#define SAFE_DELETE_ARRAY( p ) { if( p ) { delete[] ( p );   ( p ) = NULL; } }
#define SAFE_RELEASE( p )      { if( p ) { ( p )->Release(); ( p ) = NULL; } }

//-----------------------------------------------------------------------------
// Engine Includes
//-----------------------------------------------------------------------------
#include "LinkedList.h"
#include "ResourceManagement.h"
#include "Geometry.h"

//-----------------------------------------------------------------------------
// Engine Setup Structure
//-----------------------------------------------------------------------------
struct EngineSetup
{
	HINSTANCE instance; // Application instance handle.
	LPCWSTR name; // Name of the application.

	//-------------------------------------------------------------------------
	// The engine setup structure constructor.
	//-------------------------------------------------------------------------
	EngineSetup()
	{
		instance = NULL;
		name = L"Application";
	}
};

//-----------------------------------------------------------------------------
// Engine Class
//-----------------------------------------------------------------------------
class Engine
{
public:
	Engine( EngineSetup *setup = NULL );
	virtual ~Engine();

	void Run();

	HWND GetWindow();
	void SetDeactiveFlag( bool deactive );

private:
	bool m_loaded; // Indicates if the engine is loading.
	HWND m_window; // Main window handle.
	bool m_deactive; // Indicates if the application is active or not.

	EngineSetup *m_setup; // Copy of the engine setup structure.
};

//-----------------------------------------------------------------------------
// Externals
//-----------------------------------------------------------------------------
extern Engine *g_engine;

#endif
//-----------------------------------------------------------------------------
// System Includes
//-----------------------------------------------------------------------------
#include <windows.h>

//-----------------------------------------------------------------------------
// Engine Includes
//-----------------------------------------------------------------------------
#include "..\Engine\Engine.h"

//-----------------------------------------------------------------------------
// Entry point for the application.
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE instance, HINSTANCE prev, LPSTR cmdLine, int cmdShow )
{
	// Create the engine setup structure.
	EngineSetup setup;
	setup.instance = instance;
	setup.name = L"Framework Test";

	// Create the engine (using the setup structure), then run it.
	new Engine( &setup );
	g_engine->Run();

	return true;
}

Edited 5 Years Ago by Argo54325: n/a

Looking at the code, I think the problem lies here in your WinMain function:

// Create the engine (using the setup structure), then run it.
	new Engine( &setup );
	g_engine->Run();

I could be wrong but I think you need to do this:

// Create the engine (using the setup structure), then run it.
	g_engine = new Engine( &setup );
	g_engine->Run();

But then, from looking at the other errors, I'm not sure if g_engine is actually visible to WinMain....

In fact, looking at the code you've posted, g_engine is declared as an external variable in Engine.h and then you have a local pointer called g_engine in Engine.cpp... So the problem is, where exactly is the external instance of g_engine (declared in Engine.h) being held?
I think this is the problem the linker is also having.
It sees no problem with the local variable declared in Engine.cpp, but it cannot find the extern that is declared in Engine.h.

If the local instance in Engine.cpp is supposed the external instance you are referring to in Engine.h. i.e. you are trying to make the local instance externally available to other modules then perhaps you need to rethink things a little.
You can't make a local variable in the .cpp file external by declaring an extern in the header. (unless I'm terribly mistaken!)

So first up, I'd say remove the extern from Engine.h.
It also seems odd that your Engine class should store a pointer to an instance of itself. I can see that you're only using the pointer to allow the callback function to work.

If your Engine class is meant to be a singleton, then I suppose you could store an Engine pointer in your Engine classes unnamed namespace and create a static public function to allow external classes to access/modify the instance of the Engine.
So under the public section of the Engine class declaration in Engine.h:

static Engine *GetInstance();

And in Engine.cpp:

// local unnamed namespace
namespace
{
    // pointer is now static and localised to the Engine class
    Engine *g_engine=0;
}
// accessor function
Engine* Engine::GetInstance()
{
    return g_engine; // return the local static instance
}

Also to deal with creating an instance of the Engine class, you could create another public static function in Engine.h. So again, under the public section of the header:

static Engine *CreateEngine(EngineSetup &setup);

Which could be implemented in Engine.cpp like so:

// Create an instance of Engine if there isn't already one
Engine* Engine::CreateEngine(EngineSetup &setup)
{
    if(!g_engine)
        g_engine = new Engine(&setup);
    return g_engine;
}

Alternatively depending on your needs; if there was already an active instance of Engine, you could delete the existing instance before creating a new one in the above function... Completely up to you!

To create an instance of Engine in WinMain:

EngineSetup setup;
    setup.instance = instance;
    setup.name = L"Framework Test";

    Engine *p_engine = Engine::CreateEngine(setup);
    if(p_engine)
        p_engine->Run();

And if you need to access the Engine instance elsewhere in your programs code:

int someVar=-1;

    // using it the cautious way
    Engine p_eng = Engine::GetInstance();
    if(p_eng)
        someVar = p_eng->SomeIntFunction(); // calling some arbitrary/imaginary Engine function that returns an int
    
    // or if you are certain that an instance of the engine is available
    someVar = Engine::GetInstance()->SomeIntFunction()

BTW: These are merely suggestions off the top of my head. It was just to give you some ideas!

I've not compiled or sanity checked any of the code, so there may be some errors in there. Also, again these were literally off the top of my head, so there may be better ways around the problems you're having!
And once more, these would only work if your Engine class is intended as a singleton.

Anyway, hope this is of some use to you!

I think the reason why i was getting errors was due to not referencing the Engine Library to the WinMain Application. But now I've got the timeGetTime error again, How do i add winmm.lib to a static library?

This article has been dead for over six months. Start a new discussion instead.