Ошибка «Не удается найти символ .... при выполнении загрузки ...» при попытке запустить Hello World в качестве примера расширения C (dll) - PullRequest
0 голосов
/ 30 января 2019

Я использовал код C из следующего дословно: https://wiki.tcl -lang.org / page / Hello + World + как расширение + a + C +

 /*
  * hello.c -- A minimal Tcl C extension.
  */
 #include <tcl.h>

 static int 
 Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
 {
     Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1));
     return TCL_OK;
 }

 /*
  * Hello_Init -- Called when Tcl loads your extension.
  */
 int DLLEXPORT
 Hello_Init(Tcl_Interp *interp)
 {
     if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
         return TCL_ERROR;
     }
     /* changed this to check for an error - GPS */
     if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
         return TCL_ERROR;
     }
     Tcl_CreateObjCommand(interp, "hello", Hello_Cmd, NULL, NULL);
     return TCL_OK;
 }

Моя команда для компиляции является почти дословной, за исключением последнего символа, указывающего версию 8.6 Tcl вместо 8.4, и она компилируется без ошибок:

gcc -shared -o hello.dll -DUSE_TCL_STUBS -I$TCLINC -L$TCLLIB -ltclstub86

Затем я создал следующую программу Tcl:

load hello.dll Hello
puts "got here"

Но при запуске с tclsh выдается следующая ошибка:

не удается найти символ «Hello_Init» при выполнении «load ./hello.dll Hello» (файл «hello.tcl», строка 1)

Таким образом, я, по сути, следую нескольким предложениям ответа Донала Феллоуса здесь: не может найти символ "Embeddedrcall_Init" ОП там же отметил, что, как и я, это предложение) не решил их проблему.Из этого ответа я не попробовал одну вещь: «У вас должен быть экспортированный (extern« C ») символ функции в вашей библиотеке» - может ли это быть причиной разницы?Разве это не должно было быть в примере с самого начала?

По предложению кого-то на comp.lang.tcl я нашел «DLL Export Viewer», но когда я запускаю его на DLL, он сообщает о 0 найденных функциях.:( Что я делаю не так?

Может ли это быть проблемой с MinGW / gcc в Windows, и мне нужно прикусить пулю и сделать это с Visual Studio? Этого излишества я бы хотел избежать, если это возможно.

1 Ответ

0 голосов
/ 31 января 2019

Суть проблемы заключается в том, что ваша функция Hello_Init не попадает в глобальную таблицу символов, экспортируемую результирующей DLL.(Некоторые компоновщики помещают такие вещи как _Hello_Init вместо Hello_Init; Tcl адаптируется к ним прозрачно.) Символ должен быть для того, чтобы команда Tcl load работала: без него простонет последовательного способа сообщить вашему коду расширения, что такое дескриптор контекста Tcl_Interp (что позволяет ему создавать команды, переменные и т. д.)

(Если вы работали с C ++, одна из возможных проблемотсутствует extern "C", чье значение фактическое означает отключение искажения имени. Это, вероятно, не проблема здесь.)

Поскольку вы работаете в Windows - следуя символам в вашей DLL,такие как EnterCriticalSection и GetLastError - проблема, вероятно, связана именно с тем, как вы ссылаетесь.Я предполагаю, что Tcl определяет, что ваша функция имеет __declspec(dllexport) (при условии, что вы не определили STATIC_BUILD, который абсолютно не должен использоваться при создании DLL), и все же это не соблюдается.Предполагая, что вы используете достаточно современную версию GCC ... которой вы, вероятно, являетесь.

...