31

I just want to share how I found the solution to the error

No realize class procedure defined

when running a X/Motif C application. I am posting this because I only found one reference to this problem while searching online, and it contained no solutions.

I managed to solve the problem and wanted to share my findings if you do come across this problem again (Notice: I am not saying my solution will always solve this type of error).

Problem

I found this problem while running a simple C program that used the Motif and X Intrinsics toolkits.

$ gcc -Wall -c push.c
$ gcc -Wall -o push push.o -lXt -lXm
$ ./push
Error: No realize class procedure defined

The C source code was the following:

#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/PushB.h>

/* Prototype Callback function */
void pushed_fn(Widget, XtPointer, XmPushButtonCallbackStruct *);

int main(int argc, char **argv)
{
  Widget top_wid, button;
  XtAppContext  app;
  Display* display;

  XtToolkitInitialize();
  app = XtCreateApplicationContext();
  display = XtOpenDisplay(app, "localhost:10.0","push","push", NULL,0, &argc,argv);
  top_wid = XtAppCreateShell(NULL, "Form", applicationShellWidgetClass, display, NULL, 0);

  button = XmCreatePushButton(top_wid, "Push_me", NULL, 0);

  /* tell Xt to manage button */
  XtManageChild(button);

  /* attach fn to widget */
  XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) pushed_fn, NULL);

  XtRealizeWidget(top_wid); /* display widget hierarchy */
  XtAppMainLoop(app); /* enter processing loop */
  return 0;
}

void pushed_fn(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *cbs)
{
  printf("Don't Push Me!!\n");
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Miguel Rentes
  • 994
  • 1
  • 10
  • 27

2 Answers2

28

I suspected the problem could be on the libXt since the XtRealizeWidget symbol is defined in that library. I looked at it using nm but all seemed well:

$ nm -D /usr/lib/libXt.so |grep XtRealizeWidget
02b39870 T XtRealizeWidget

The "T" means the symbol is in the text (code) section of the object files that compose the libXt library, so this symbol is defined. The path for the system libraries was also correct and I only had a single version of libXt.

I then thought that the order in which the libraries were being passed on to the gcc linker might be the cause and started reading about it, ending up on this stackoverflow thread

After switching the order of the libraries to:

$ gcc -Wall -o push push.o -lXm -lXt

the problem was solved.

Pay attention to the order in which the libraries and being passed to the linker!

Community
  • 1
  • 1
Miguel Rentes
  • 994
  • 1
  • 10
  • 27
  • 1
    Though I can't bring the exact reference to X11/Motif programming manual, I'm pretty sure many manuals/tutorials put it straight: `lXm` should be linked before `lXt` and `lX11`. At least, *LessTif* FAQ has the corresponding [note](http://lesstif.sourceforge.net/FAQ.html#QU3.0). See also this Debian [bug report](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=718691) (there's plenty of them). – Bass Oct 19 '15 at 12:15
1

The answer by Martin Simmons (taken from LessTif FAQ):

The linking order problems are caused by these two symbols:

vendorShellClassRec
vendorShellWidgetClass

which are defined AND referenced in both -lXm and -lXt. Somehow you have to convince the linker to use the -lXm definitions to satisfy the references in both -lXm and -lXt. The -lXt definitions should not be used. For typical elf-based dynamic loaders (Linux, Solaris etc), this is done by passing '-lXm -lXt' to the linker, which adds them both as SO_NEEDED sections to the executable. At runtime, the dynamic loader collects symbols from each SO_NEEDED section in the order it finds them, discarding symbols it already knows, and then fixes the references in all the loaded libraries using that combined symbol table. For typical static linkers, it is also done by specifying '-lXm -lXt' to the linker. In this case, the linker extracts some .o's from -lXm which contain user-referenced symbols and eventually ends up extracting -lXm:Vendor.o due to internal references in -lXm. It then does the same for -lXt, but doesn't need to extract -lXt:Vendor.o because it doesn't define anything that is still undefined.

Bass
  • 4,977
  • 2
  • 36
  • 82