2009-09-08 9 views
4

Après avoir essayé plusieurs et l'option web de recherche pour compiler et charger dll je ne pouvais pas créer dll pour tcl. Pouvez-vous m'expliquer comment faire cela?Comment compiler dll chargeable en tcl

+0

essayé le code à partir http://wiki.tcl.tk/2419 et le succès, mais n'a pas pu ajouter des fonctions propres (par exemple HelloObjCmdProc) – OliveOne

+0

Pouvons-nous voir le code que vous avez jusqu'à présent et les erreurs que vous obtenez? Est-ce que le code compile mais ne parvient pas à charger dans TCL? Quel compilateur utilisez-vous pour construire la DLL avec? – Jackson

Répondre

8

Ok, voici un exemple simple. Ce code compile et fonctionne pour Tcl8.5 et VS2008. Pour commencer, j'ai créé un projet dll WIN32 appelé BasicTclExtn qui exportait des symboles.

// BasicTclExtn.h 
#ifdef BASICTCLEXTN_EXPORTS 
#define BASICTCLEXTN_API __declspec(dllexport) 
#else 
#define BASICTCLEXTN_API __declspec(dllimport) 
#endif 

int BasicExtnCmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) ; 
extern "C" { 
    BASICTCLEXTN_API int Basictclextn_Init(Tcl_Interp *interp) ; 
} 

Et puis le fichier .cpp

// BasicTclExtn.cpp : Defines the exported functions for the DLL application. 
#include "stdafx.h" 
#include "BasicTclExtn.h" 

int 
BasicExtnCmd(ClientData data, 
      Tcl_Interp *interp, 
      int objc, 
      Tcl_Obj *CONST objv[]) 
{ 

    // Check the number of arguments 
    if (objc != 3) { 
     Tcl_WrongNumArgs(interp, 1, objv, "arg arg"); 
     return TCL_ERROR; 
    } 

    long v1, v2, result ; 

    if (Tcl_GetLongFromObj(interp, objv[1], &v1) != TCL_OK) 
     return TCL_ERROR ; 

    if (Tcl_GetLongFromObj(interp, objv[2], &v2) != TCL_OK) 
     return TCL_ERROR ; 

    result = v1 + v2 ; 

    Tcl_SetObjResult(interp, Tcl_NewIntObj(result)) ; 
     return TCL_OK ; 
} 

    // Note the casing on the _Init function name 
    BASICTCLEXTN_API int Basictclextn_Init(Tcl_Interp *interp) 
    { 
     // Link with the stubs library to make the extension as portable as possible 
     if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { 
      return TCL_ERROR; 
     } 

     // Declare which package and version is provided by this C code 
     if (Tcl_PkgProvide(interp, "BasicTclExtn", "1.0") != TCL_OK) { 
      return TCL_ERROR ; 
     } 

     // Create a command 
     Tcl_CreateObjCommand(interp, "BasicExtnCmd", BasicExtnCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); 

     return TCL_OK ; 
    } 

Vous devez #inclure tcl.h dans le stdafx.h.

Cet exemple utilise la fonction TLS stubs, voir la documentation de la fonction Tcl_InitStubs pour plus d'informations. Lorsque vous utilisez des stubs, vous devez uniquement lier le fichier tclstub85.lib. Pour obtenir le code pour lier correctement, vous devez effectuer les opérations suivantes:

  • Ajouter le include où tcl.h est installé aux propriétés de configuration -> C/C++ -> Général -> supplémentaires répertoires d'
  • Définir le symbole USE_TCL_STUBS, je le fais normalement dans Propriétés -> C/C++ -> Préprocesseur -> Définitions du préprocesseur. Vous pouvez également trouver que vous devez ensuite définir le <DLLNAME>_EXPORTS (BASICTCLEXTN_EXPORTS dans mon exemple) après cela, je ne sais pas pourquoi cela se produit.
  • Ajoutez le chemin d'accès au répertoire où se trouve le fichier tclstub85.lib en tant que répertoire de bibliothèque supplémentaire dans Propriétés de configuration -> Lieur -> Général -> Répertoires de bibliothèques supplémentaires.
  • Ajouter tclstub85.lib aux propriétés de configuration -> Linker -> Entrée -> D'autres
  • Dépendances
  • Si le compilateur recrache un avertissement sur MSVCRT puis exclure MSVCRT en l'ajoutant aux bibliothèques ignorées dans Propriétés de configuration -> Linker -> Entrée -> Ignorer une bibliothèque spécifique.

Tous ces fichiers .lib, .dll et .h devraient être facilement trouvés dans votre installation Tcl. Vous devez également vous assurer que les fichiers tclstub85.dll et tcl85.dll associés peuvent être trouvés lors de l'exécution, en vérifiant que le répertoire bin de Tcl est sur le PATH. Donc, vous devriez alors être en mesure de faire ce qui suit de Tcl:

C:\Projects\BasicTclExtn\Debug>tclsh 
% load BasicTclExtn.dll 
% BasicExtnCmd 1 2 
3 
% BasicExtnCmd 1 2.p 
expected integer but got "2.p" 
% BasicExtnCmd 1 2 
3 
% BasicExtnCmd 1 
wrong # args: should be "BasicExtnCmd arg arg" 
% BasicExtnCmd 1 3 
4 
% exit 

Ceci est la forme la plus simple de Tcl exstention, vous pouvez ajouter des appels supplémentaires à Tcl_CreateObjCommand() ajouter d'autres commnds dans cette extension. Tcl fournit quelques faciities pour aider au traitement des paramtres de ligne de commande passs dans la commande. L'exemple de code utilisé Tcl_WrongNumArgs() mais vous devriez également regarder les fonctions Tcl_GetIndexFromObj().

Je vous suggère également d'obtenir une copie de Practical Programming in Tcl and Tk de Brent Welch. Vous pouvez lire un exemple de chapitre ici http://www.beedub.com/book/, le chapitre sur la programmation C pour Tcl de la 3ème édition vous aidera beaucoup.

+0

BasicTclExtn.obj: erreur LNK2019: symbole externe non résolu __imp__Tcl_SetObjResult référencé dans la fonction "int __cdecl BasicExtnCmd (void *, structure Tcl_Interp *, int, struct Tcl_Obj * const * const)" (?BasicExtnCmd @@ YAHPAXPAUTcl_Interp @@ HQBQAUTcl_Obj @@@ Z) – OliveOne

+0

après avoir essayé de compiler sur VS 2008 et tcl8.5 avec tous les paramètres de include et lib. – OliveOne

+0

Avez-vous utilisé l'en-tête précompilé? J'ai utilisé le projet vide et ajouté stdafx.h séparé dans include – OliveOne