2015-09-03 3 views
31

Я просто хочу поделиться тем, как я нашел решение ошибкиНет процедуры класса понимают не определен

Нет процедуры класса понимают не определен

при запуске X/Motif C приложения. Я публикую это, потому что я нашел только одну ссылку на эту проблему во время поиска в Интернете, и в ней не было никаких решений.

мне удалось решить эту проблему и хотел бы поделиться своими выводами, если вы столкнетесь с этой проблемой снова (Примечания: Я не говорю, что мое решение будет всегда решить этот тип ошибки).

Проблема

Я нашел эту проблему во время работы простой программы C, которые использовали наборы инструментов Motif и X Intrinsics.

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

ответ

28

Я подозревал, что проблема может быть на libXt, так как символ XtRealizeWidget определяется в этой библиотеке. Я смотрел на него с помощью нм, но все казалось хорошо:

$ 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

Хотя я не могу привести точную ссылку на руководство по программированию X11/Motif, я уверен, что многие руководства/учебники ставят его прямо: 'lXm' должен быть связан до' lXt' и 'lX11'. По крайней мере, * LessTif * FAQ имеет соответствующую [примечание] (http://lesstif.sourceforge.net/FAQ.html#QU3.0). См. Также этот Debian [отчет об ошибках] (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=718691) (их много). – Bass

1

Ответ на Мартин Симмонс (из LessTif FAQ):

Увязка проблемы порядка вызваны этими двумя символами:

vendorShellClassRec 
vendorShellWidgetClass 

которые определены и ссылки в обоих -lXm и -lXt. Как-то вам нужно убедить компоновщика использовать определения -lXm для удовлетворения ссылок как в -lXm, так и в -lXt. Определения -lXt не должны использоваться. Для типичных динамических загрузчиков на основе эльфов (Linux, Solaris и т. Д.) Это делается путем передачи '-lXm -lXt' в компоновщик, который добавляет их как SO_NEEDED к исполняемому файлу.Во время выполнения динамический загрузчик собирает символы из каждого раздела SO_NEEDED в том порядке, в котором он их находит, отбрасывая символы, которые он уже знает, а затем исправляет ссылки во всех загруженных библиотеках, используя эту комбинированную таблицу символов. Для типичных статических компоновщиков это также делается путем указания '-lXm -lXt' на компоновщик. В этом случае компоновщик извлекает некоторые .o из -lXm, которые содержат символы, обозначенные пользователем, и в конечном итоге заканчиваются извлечением -lXm:Vendor.o из-за внутренних ссылок в -lXm. Затем он делает то же самое для -lXt, но не нужно извлекать -lXt:Vendor.o, потому что он не определяет ничего, что еще не определено.