[ATL/COM] Lnk1169 - circular dependencies??

Post questions, comments and feedback to our 3Dconnexion Windows Development Team.

Moderator: Moderators

Post Reply
neobond
Posts: 13
Joined: Wed Jul 04, 2007 4:11 am

[ATL/COM] Lnk1169 - circular dependencies??

Post by neobond »

Hello...

in conjunction to my university project, I integrated the SpaceNavigator into our existing framework (C++, Qt-based, QTOpenGL) for Medical Volume Data Analysis and Segmentation (and further more).

And what to say, I like the SpaceNavigator, it is the right thing to augment working!!!

But now it comes: I am a total novice to ATL/COM etc... and it seems that I have a circular dependency problem!

3 classes: HardwareManager (creates SpaceNavigator-Object), SpaceNavigator and Qt-GLWidget (manages Shortcuts for switching cameraMovement, volumeMovement and SliceMovement)

When I compile (only sometimes, when there have been changes in HardwareManager or GLWidget) the VS2005-Compiler throws

fatal error LNK1169: Mindestens ein mehrfach definiertes Symbol gefunden. (kinda at least one multiple symbols defined symbol found)

How can I resolve this???

What works, but is not very intuitive: comment out
[module(name="EventReceiver")];
and
[event_receiver(com)]
compile and comment them in after another?!

I've seen and tested the example programes like ATLCube... But I did implement only the minimum to get the program compile and run.


Regards
Andi
Last edited by neobond on Wed Jul 04, 2007 10:25 am, edited 1 time in total.
neobond
Posts: 13
Joined: Wed Jul 04, 2007 4:11 am

Some Code

Post by neobond »

It might be useful to see some code snippets....

HardwareManager.cpp

Code: Select all

HardwareManager::HardwareManager(void){
	//TODO: integrate, test Phantom

#ifdef USE_SPACENAV
	mSpaceNavigator = new SpaceNavigator();
#endif
}
SpaceNavigator.h

Code: Select all

#ifdef USE_SPACENAV

#define _ATL_ATTRIBUTES

#include <atlbase>
#include <atlcom>
//#include <atlwin>
//#include <atltypes>
//#include <atlctl>
//#include <atlhost>

using namespace ATL;

//if SpaceNavigator is installed
//#import "progid:TDxInput.Device" embedded_idl no_namespace
//if only support-files are available
#import "..\..\support\SpaceNavigator\TDxInput.dll" embedded_idl no_namespace

//circular dependency of included SpaceNavigator in HardwareManager.h and GLWidget.h (TODO:resolve)
//when retrieving compile error 
//     compile without [module(..)] and [event..] lines (uncomment!)
//then compile with [event_receiver(com)] option
//then compile with [module(name="EventReceiver")]; option

[module(name="EventReceiver")];

[event_receiver(com)]
#endif
class SpaceNavigator{
	public:
		SpaceNavigator();
		~SpaceNavigator();

		bool deviceFound;
		void setMoveMode( string mode);
[...]
SpaceNavigator.cpp

Code: Select all

SpaceNavigator::SpaceNavigator(){

	//for global referencing if SpaceNavigator has been found!
	deviceFound = false; 

#ifdef USE_SPACENAV

	//initializing input values from sensor
	x_trans = 0.0, y_trans = 0.0, z_trans = 0.0;
	x_vert  = 0.0, y_vert  = 0.0, z_vert  = 0.0;
	x_rot   = 0.0, y_rot   = 0.0, z_rot   = 0.0, angle_rot = 0.0;
	moveVolume = false; moveCamera = true; moveSlices = false;

	mHR = mPDevice.CreateInstance(__uuidof(Device));
	if ( SUCCEEDED( mHR ) ) { 
		
		mHR = mPDevice->Connect();  //will always be true, when driver is found;
									//even when there is no SpaveNavigator connected
		if ( SUCCEEDED( mHR ) ) {	// && mPDevice->Type == 6 SpaceNavigator has TypeId = 6

			//registrate (hook_in) the functions to DevicePointers and internal Operations
			mHR = __hook(&_ISimpleDeviceEvents::DeviceChange, mPDevice, &SpaceNavigator::OnDeviceChange);
			mHR = mPDevice->get_Sensor  (&mP3DSensor);
			mHR = __hook(&_ISensorEvents::SensorInput, mP3DSensor, &SpaceNavigator::OnSensorInput);

			mHR = mPDevice->get_Keyboard(&mP3DKeyboard);
			mHR = __hook(&_IKeyboardEvents::KeyDown, mP3DKeyboard, &SpaceNavigator::OnKeyDown);
			mHR = __hook(&_IKeyboardEvents::KeyUp,   mP3DKeyboard, &SpaceNavigator::OnKeyUp);

			//mPDevice->LoadPreferences("MedGPU");
			QTLogWindow::the()->addDebug( "SpaceNavigator  ::SpaceNavigator() - SpaceNavigator initialized correctly" );

			deviceFound   = true; 
		}
		else {
			mPDevice = NULL;
			QTLogWindow::the()->addError( "SpaceNavigator  ::SpaceNavigator() - sorry, unknown device type detected" );
		}
	} 
	else{
		QTLogWindow::the()->addError( "SpaceNavigator  ::SpaceNavigator() - driver not installed" );
	}
#endif
}
[/code]
mbonk
Moderator
Moderator
Posts: 181
Joined: Mon Dec 04, 2006 4:06 am

Post by mbonk »

Hi neobond,

What does the build output say about which symbols are causing the problem?
Even if its in german cut and paste the relevant entries.

btw please do a clean first.

Markus
neobond
Posts: 13
Joined: Wed Jul 04, 2007 4:11 am

Post by neobond »

Hello Markus,

here is what he says when 1)Clean Solution 2) Build Solution

Code: Select all

Linking...
GLWidget.obj : error LNK2005: _DllGetClassObject@12 already defined in HardwareManager.obj
GLWidget.obj : error LNK2005: _DllRegisterServer@0 already defined in HardwareManager.obj
GLWidget.obj : error LNK2005: _DllUnregisterServer@0 already defined in HardwareManager.obj
GLWidget.obj : error LNK2005: _DllCanUnloadNow@0 already defined in HardwareManager.obj
GLWidget.obj : error LNK2005: _DllMain@12 already defined in HardwareManager.obj
GLWidget.obj : error LNK2005: "class CEventReceiverModule _AtlModule" (?_AtlModule@@3VCEventReceiverModule@@A) already defined in HardwareManager.obj
SpaceNavigator.obj : error LNK2005: _DllGetClassObject@12 already defined in HardwareManager.obj
SpaceNavigator.obj : error LNK2005: _DllRegisterServer@0 already defined in HardwareManager.obj
SpaceNavigator.obj : error LNK2005: _DllUnregisterServer@0 already defined in HardwareManager.obj
SpaceNavigator.obj : error LNK2005: _DllCanUnloadNow@0 already defined in HardwareManager.obj
SpaceNavigator.obj : error LNK2005: _DllMain@12 already defined in HardwareManager.obj
SpaceNavigator.obj : error LNK2005: "class CEventReceiverModule _AtlModule" (?_AtlModule@@3VCEventReceiverModule@@A) already defined in HardwareManager.obj
Regards
Andreas
mbonk
Moderator
Moderator
Posts: 181
Joined: Mon Dec 04, 2006 4:06 am

Post by mbonk »

Hi neobond,

Try moving the

Code: Select all

[module(name="EventReceiver")];
out of SpaceNavigator.h and
into SpaceNavigator.cpp and
let me know what the result is.

Markus
neobond
Posts: 13
Joined: Wed Jul 04, 2007 4:11 am

SOLVED!!!!

Post by neobond »

Great: IT WORKS!!!!

it now starts in Debug AND Release Mode.
And also the Compile Errors vanished ( and I also understood why :D )

One last question from an ATL newbie:
what is

Code: Select all

[module(name="EventReceiver")];
exactly for????

what would be the advantage of

Code: Select all

[module(type=dll, name="EventReceiver", uuid="9217D439-8DFE-4C2E-9329-7D95B5FCD5DC")];
if there is any???

THANX a lot
Andreas
mbonk
Moderator
Moderator
Posts: 181
Joined: Mon Dec 04, 2006 4:06 am

Post by mbonk »

Asa far as I know

Code: Select all

[module(name="EventReceiver")];
Is firstly required in any program that uses C++ attributes and an interface definition language file is created by the compiler. This file defines the characteristics, data and methods of the COM interface. The alternative appears to be to write the thing yourself. This has nothing to do with ATL.

If you happen to be using ATL then the module attribute also inserts a global object called _AtlModule.

setting type=dll, which is the default adds functions required to register etc a Com server in a dll.

without uuid="uuid" an ID is automatically generated.

Markus
Post Reply