2011-03-08 7 views
3

J'ai un projet, où je dois me connecter à une bibliothèque basée sur C, et je n'ai pas pu obtenir les fonctions de C# en utilisant le DLLImport. Je dois utiliser un projet C++/CLI basé sur ces fonctions pour les utiliser. (plus à cette histoire mais pas important).Visual C++/CLI - Classe CLR - LNK2020 Erreur - Comment réparer?

J'ai étudié le C++ il y a plus de 10 ans, alors pardonnez-moi si cela semble naïf.
J'ai acheté quelques livres sur la mise en œuvre C++/CLI l'année dernière, et j'ai une idée de ce qui est en jeu - j'ai seulement creusé dans ces livres pour ce projet. (Je suis programmeur depuis longtemps).

Je pensais que je devrais commencer un petit projet d'exemple de projet pour me familiariser avec ce qui sera impliqué, pour s'assurer que je pourrais compiler, etc. J'ai commencé un projet en utilisant Visual Studio 2008 SP1; Visual C++> CLR> Bibliothèque de classes. Dans le projet - je veux utiliser à la fois géré et natif de la DLL. Donc, le commutateur/clr est utilisé. J'ai utilisé d'autres noms dans le code réel; mais c'est très, très proche. (Il n'y a pas d'autres fichiers ou fonctions à ce stade)

tête:

//myWrapper.h 
#pragma once 
using namespace System; 
namespace myWrapper { 
    public ref class myWrappedService { 
     myWrappedService(); 
     bool Connected(String ^user,String ^password,String ^domain); 
    } 
}; 

Et la mise en œuvre a cela.

//myWrapper.cpp 
//This is the main DLL file 
#include "stdafx.h" 
#include "myWrapper.h" 
using namespace System; 
public ref class myWrappedService 
    { 
     public: 
      myWrappedService() {} 
      bool Connected(String ^user,String ^password,String ^domain) 
      { 
       //just a simple result to start - no real functionality 
       bool result = false; 
       return result; 
      } 
    }; 

C'est le code - qui compile mais reçoit des erreurs de liens.

erreur LNK2020: jeton non résolu (06000002) myWrapper.myWrappedService :: connectés

LNK1120 d'erreur fatale: 1 sans solution externe.

Cela a semblé mort-facile - et je pourrais penser beaucoup à partir d'une approche C#. Je m'attends à ce que ce soit quelque chose de simple - mais je ne suis pas familier avec ce que je devrais voir dans l'approche CLI. (J'ai passé quelques heures à chercher des réponses et je sens finalement que j'ai besoin de poser une question à laquelle on pourrait répondre).

Répondre

4
namespace myWrapper { 

Cela a mal tourné à partir de là. Votre fichier .h déclare une classe à l'intérieur de cet espace de noms, son nom est myWrapper :: myWrappedService. Votre fichier .cpp déclare une autre classe qui n'est pas dans un espace de noms, son nom est :: myWrappedService. Différents noms, le compilateur ne se plaindra pas de voir la même classe définie deux fois. La première classe n'a pas une implémentation de la méthode Connected, c'est pourquoi l'éditeur de liens s'est plaint.

Les extraits de sad_man présentent le même défaut. Le premier extrait définit la méthode :: myWrappedService :: Connected(). Mauvais espace de noms.Le deuxième extrait a le même défaut que le vôtre. Lorsque vous écrivez une bibliothèque de classes dans du code managé, vous n'avez pas besoin d'un fichier .h. Les métadonnées dans un assembly jouent le même rôle, elles contiennent les déclarations des types dans l'assembly. Il n'y a pas d'autre fichier .cpp dans votre projet qui nécessite la déclaration de la classe, pas besoin de .h. Donc, il suffit d'écrire tout dans le fichier .cpp:

#include "stdafx.h" 
// Note: header file removed 

using namespace System; 

namespace myWrapper { 

    public ref class myWrappedService 
    { 
    public: 
     myWrappedService() {} 
     void Connect(String ^user, String ^password, String ^domain) 
     { 
      throw gcnew NotImplementedException; 
     } 
    }; 
} 
+0

J'ai essayé votre approche - la ligne Connect se plaint d'une erreur 3149: 'System :: String' ne peut pas utiliser ce type sans un '^' de niveau supérieur. J'ai également besoin d'une valeur de retour pour dire que je me suis connecté - si vous pouviez modifier votre exemple - pourrait fonctionner. – Wolfledge

+0

J'ai vérifié que ce code était compilé et intégré dans un assemblage de travail avant que je n'envoie. Les arguments String de Connect() ont clairement un^visible dans l'extrait, vérifiez votre copie. Je pense que vous pouvez comprendre comment changer le type de retour de la méthode par vous-même. –

+0

ma mauvaise - faute de frappe - et en utilisant mon type de retour, il compilé. Et quand j'ai ouvert la DLL avec réflecteur, la méthode était là. Je vous remercie. – Wolfledge

2

Votre fichier cpp est erroné. Pour l'utilisation de cpp un fichiers d'en-tête regardent here et here. C++/Cli a le même concept de fichiers header et cpp. En fait, votre fichier cpp est ce qu'un fichier d'en-tête est censé être.

vous pouvez aussi aller comme ceci:

//myWrapper.h 
#pragma once 
#include "stdafx.h" 
using namespace System; 
namespace myWrapper { 
    public ref class myWrappedService { 
     myWrappedService(); 
     bool Connected(String ^user,String ^password,String ^domain); 
    } 
}; 

//myWrapper.cpp 
//This is the main DLL file 
#include "stdafx.h" 
#include "myWrapper.h" 
using namespace System; 
namespace myWrapper 
{ 
    myWrappedService::myWrappedService() {} 
    bool myWrappedService::Connected(String ^user,String ^password,String ^domain) 
    { 
     bool result = false; 
     return result; 
    } 
} 

Ou comme celui-ci (un en-tête pour votre cas):

//myWrapper.h 
//This is the main DLL file 
#include "myWrapper.h" 
using namespace System; 
namespace myWrapper 
{ 
public ref class myWrappedService 
    { 
     public: 
      myWrappedService() {} 
      bool Connected(String ^user,String ^password,String ^domain) 
      { 
       //just a simple result to start - no real functionality 
       bool result = false; 
       return result; 
      } 
    }; 
} 
    // Remember? this was your cpp. 

EDIT: J'ai oublié l'espace de noms. Mais je pense que vous devriez apprendre ce que sont les fichiers header et cpp.

+0

J'ai essayé votre 1er exemple - sur la base de code avec les noms réels - ne fonctionnait pas. J'ai ensuite créé un nouveau projet en utilisant ces noms d'exemples - même problème (pas même une compilation). Je pense que vous essayez de souligner la séparation entre l'en-tête et l'implémentation. – Wolfledge

+0

J'ai ensuite essayé votre approche "en-tête seulement" - qui compile et lie - cependant le réflecteur pointant sur la DLL montre que la méthode n'apparaît jamais. – Wolfledge