没有实现 class 程序定义
No realize class procedure defined
我只想分享我是如何找到错误的解决方案的
No realize class procedure defined
当 运行 一个 X/Motif C 应用程序时。我发布这个是因为我在网上搜索时只找到一个关于这个问题的参考,而且它没有包含解决方案。
我设法解决了这个问题,如果您再次遇到这个问题,我想分享我的发现(注意:我并不是说我的解决方案会 总是解决这类错误)。
问题
我在 运行 使用 Motif 和 X Intrinsics 工具包的简单 C 程序时发现了这个问题。
$ gcc -Wall -c push.c
$ gcc -Wall -o push push.o -lXt -lXm
$ ./push
Error: No realize class procedure defined
C 源代码如下:
#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");
}
我怀疑问题可能出在 libXt 上,因为 XtRealizeWidget 符号是在该库中定义的。我用 nm 查看了它,但一切似乎都很好:
$ nm -D /usr/lib/libXt.so |grep XtRealizeWidget
02b39870 T XtRealizeWidget
"T"表示符号在组成libXt库的目标文件的文本(代码)部分,所以定义了这个符号。系统库的路径也是正确的,我只有一个版本的 libXt。
然后我认为库传递给 gcc 链接器的顺序可能是原因并开始阅读它,最后看到这个 Whosebug thread
将库的顺序切换为:
$ gcc -Wall -o push push.o -lXm -lXt
问题已解决。
注意库和传递给链接器的顺序!
Martin Simmons的回答(摘自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.
我只想分享我是如何找到错误的解决方案的
No realize class procedure defined
当 运行 一个 X/Motif C 应用程序时。我发布这个是因为我在网上搜索时只找到一个关于这个问题的参考,而且它没有包含解决方案。
我设法解决了这个问题,如果您再次遇到这个问题,我想分享我的发现(注意:我并不是说我的解决方案会 总是解决这类错误)。
问题
我在 运行 使用 Motif 和 X Intrinsics 工具包的简单 C 程序时发现了这个问题。
$ gcc -Wall -c push.c
$ gcc -Wall -o push push.o -lXt -lXm
$ ./push
Error: No realize class procedure defined
C 源代码如下:
#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");
}
我怀疑问题可能出在 libXt 上,因为 XtRealizeWidget 符号是在该库中定义的。我用 nm 查看了它,但一切似乎都很好:
$ nm -D /usr/lib/libXt.so |grep XtRealizeWidget
02b39870 T XtRealizeWidget
"T"表示符号在组成libXt库的目标文件的文本(代码)部分,所以定义了这个符号。系统库的路径也是正确的,我只有一个版本的 libXt。
然后我认为库传递给 gcc 链接器的顺序可能是原因并开始阅读它,最后看到这个 Whosebug thread
将库的顺序切换为:
$ gcc -Wall -o push push.o -lXm -lXt
问题已解决。
注意库和传递给链接器的顺序!
Martin Simmons的回答(摘自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 asSO_NEEDED
sections to the executable. At runtime, the dynamic loader collects symbols from eachSO_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.