没有实现类程序的定义

时间:2015-09-03 10:56:40

标签: c gcc x11 ld motif

我只想分享我是如何找到错误的解决方案

  

没有实现类程序的定义

运行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");
}

2 个答案:

答案 0 :(得分:28)

我怀疑问题可能出在libXt上,因为XtRealizeWidget符号是在该库中定义的。我用nm看着它,但一切看起来都很好:

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

“T”表示符号位于组成libXt库的目标文件的文本(代码)部分,因此定义了此符号。系统库的路径也是正确的,我只有一个版本的libXt。

然后我认为将库传递给gcc链接器的顺序可能是原因,并开始阅读它,最后得到stackoverflow thread

将库的顺序切换为:

$ gcc -Wall -o push push.o -lXm -lXt
问题解决了。

注意库和传递给链接器的顺序!

答案 1 :(得分:1)

Martin Simmons的回答(摘自LessTif FAQ):

  

链接顺序问题是由这两个符号引起的:

vendorShellClassRec
vendorShellWidgetClass
     

-lXm-lXt中引用了 AND 。不知何故,您必须说服链接器使用-lXm定义来满足-lXm-lXt中的引用。不应使用-lXt定义。对于典型的基于elf的动态加载器( Linux Solaris 等),可以通过将'-lXm -lXt'传递给链接器来完成,链接器将它们都添加为{{1可执行文件的部分。在运行时,动态加载程序按照它们找到的顺序从每个SO_NEEDED部分收集符号,丢弃它已知的符号,然后使用该组合符号表修复所有加载库中的引用。对于典型的静态链接器,也可以通过为链接器指定SO_NEEDED来完成。在这种情况下,链接器从'-lXm -lXt'中提取包含用户引用符号的一些.o,并最终由于-lXm中的内部引用而最终提取-lXm:Vendor.o。然后它对-lXm执行相同的操作,但不需要提取-lXt,因为它没有定义任何仍未定义的内容。