[vtkusers] Can't execute point picking with following code

Obada Mahdi omahdi at gmx.de
Sat Jul 14 07:36:57 EDT 2007


Hi Flo,

it looks like you just forgot to actually define the static member 
variable "SimpleView::This":

Flo wrote:
> In a class SimpleView I have:
> 
> public:
> static void Test(vtkObject* vtkNotUsed(object),unsigned long event,void* 
> clientdata, void* vtkNotUsed(calldata));
> 
> private:
> static SimpleView *This;
> 
> and in the SimpleView constructor I declared:
> This=this
> 
> Finally, in Test I do as follows:
> 
> SimpleView::This->MouseMotion (also tried This->MouseMotion ) and same 
> for iren, ren and picker
> 
> 
> BUT then during the linking process I have the following error:
> /usr/bin/ld: Undefined symbols:
> SimpleView::This

The declaration "static SimpleView *This;" within the class declaration 
does not actually define (i.e. "reserve space") for that symbol, it just 
announces its existence (that's why the compiler doesn't complain).
Just put a

| SimpleView *This = 0;

(without the "static" keyword) somewhere in your implementation -- .cc, 
.cxx, or whatever extension you are using :-)


> On 10-Jul-07, at 7:33 AM, Luca Pallozzi Lavorante wrote:
> 
>> Dear Flo, I have had a similar problem and the solution I adopted may 
>> not be elegant but it works. Use a static attribute ( i.e., "This", 
>> note the uppercase "T") that you  can use in the callback. The 
>> attribute is a pointer to a class PLUS. PLUS´s constructor would 
>> initialize it to "this" (something like "This = this"). Another 
>> solution would be to make static all the pointer attributes you need 
>> to use in your callback (iren ren, picker and so on...). I also tried 
>> this second path but I found it is a lit more messy.

Given that "SimpleView" is meant to be a true singleton design (i.e. 
there is at most one living instance at any time), the solution with a 
static pointer is perfectly fine, especially because there should be one 
to record the only existing instance (if any) anyway.

There is a more general, slightly different technique for binding a 
callback object (or function) to a particular instance, and VTK actually 
offers a simple mechanism for doing this through the SetClientData() 
method of vtkCallbackCommand.  This "client data" simply is a single 
void pointer, which is passed on to the callback function unmodified.

The idea is that you can define some kind of context for the callback 
handler by setting up the "client data" pointer as you see fit upon 
initialization of the callback object, and then use this context later 
within the handler.  In your case, Flo, you might just set up the 
callback's client data to point to the SimpleView instance, and cast it 
back appropriately in the static callback handler, just as you have done 
it with the vtkInteractorStyle instance.  Accessibility of the 
interactor style instance is retained if passing on the SimpleView 
instance instead, you can obtain it just as any other instance variable 
of SimpleView.

In even larger or more complicated scenarios, it might be appropriate to
have a dedicated struct or class for recording necessary callback context.


HTH,

Obada



More information about the vtkusers mailing list