2009-12-01 8 views
0

Je tente de consommer une DLL écrite en C++ à partir d'une application C#. J'ai un code source tiers pour la DLL C++ (le moteur physique Cyclone) et je ne veux pas le porter manuellement sur C#.Utilisation d'une DLL C++ en C#

Dans le projet C++
je l'ai changé pour produire une dll. Je l'ai changé pour utiliser le drapeau/clr. Je l'ai changé pour utiliser la DLL de débogage Multi-threaded (/ MDd) parce que c'était le seul compatible avec/clr et aussi compilé.

Dans le projet C#
J'ai ajouté une référence à la dll. J'utilise l'espace de noms cyclone.

Au début, il n'y avait absolument rien sous l'espace de noms. Je pense que c'est parce que dans le code C++, toutes les classes ont été déclarées sans modificateurs d'accès et la valeur par défaut est private. Donc, pour la classe « particules » J'ai changé la définition:

public class Particle 
{ 
//... 
} 

Maintenant, je peux déclarer avec succès une variable de type de particules à partir du code C#. Cependant, intellesense et le navigateur d'objets rapportent que Particle est une structure (?) Et ne contient aucune méthode. Le code C++ déclare un tas de méthodes après les modificateurs d'accès "public:" donc je ne sais pas quel est le problème.

Par exemple,

public: 
void integrate(real duration); 

Qu'est-ce que je fais mal?

Répondre

2

La classe Particle n'étant pas une classe managée, elle est traitée comme une structure. Vous devez utiliser le mot-clé ref pour le gérer et le ramasser. Vous devez également faire la même chose pour toutes les autres classes qui le référencent, ce qui pourrait poser problème. La meilleure solution, je pense, est de créer une classe wrapper gérée qui utilise la classe Particle en interne. Cette classe wrapper peut ensuite être référencée par .net.

Voir here:

+0

Merci, garder les différences entre C# et C++ est très difficile pour moi pour une raison quelconque ... L'outil P/Invoke Interop Assistant référencé par Caelum être capable de générer un wrapper automatiquement? Ou y a-t-il d'autres outils qui peuvent accomplir cela? – colithium

+0

P/Invoke est un moyen d'appeler du code natif qui n'est pas compilé avec/clr. Vous ne pourrez toujours pas instancier la classe, vous pouvez seulement appeler des fonctions. Une autre approche peut consister à laisser la DLL en l'état et à créer une nouvelle DLL C++ managée. Celui-ci contient une API gérée, conçue pour être facile à utiliser depuis .net. L'implémentation appelle ensuite la DLL native. Vous devriez facilement trouver des exemples de travail sur le net. –

0

Essayez déclarant la C++ classe avec le mot-clé ref:

public ref class Particle 
+0

245 erreurs de compilation quand j'ajoute qu'un petit mot clé à la classe de particules ... Peut-être il est impossible d'utiliser l'option clr à moins qu'il a été écrit spécifiquement pour elle? Je sais que ce code a été écrit comme une pure bibliothèque C++ sans aucune réflexion.NET – colithium

+0

Pour quelque chose comme ça je créerais un wrapper "ParticleBridge" classe qui encapsule la classe de particules. Laissez le code original tel quel pour qu'il se compile avec succès, et dans votre nouveau ParticleBridge, ayez un membre privé d'une instance de particule, de sorte que les fonctions appelées par ParticleBridge appellent à leur tour la fonction de cette particule. Vous aurez besoin de faire quelques lectures sur la façon de gérer les types gérés et les pointeurs de C++/CLI. – AaronLS

0

Avez-vous une référence à COM Interop?

+0

Je pensais que lorsque vous avez spécifié l'indicateur/clr, il a bien fonctionné avec les applications .NET et que vous n'avez pas besoin d'utiliser Interop. Au moins, c'est ce que j'ai glané en cherchant si. Mais pour répondre à votre question: je ne le pense pas – colithium

+0

La raison pour laquelle je demande est qu'avec la plupart des dll C++ que j'ai utilisés, j'ai utilisé une interface COM. – Soppus

1

Je n'ai pas réellement rencontré votre problème exact auparavant, mais j'ai déjà utilisé des dll C++ dans C# auparavant. En règle générale, lorsque vous appelez un DLL, vous utilisez le mot-clé dllImport. Fondamentalement, vous pouvez définir une classe qui importe tous les types et méthodes de la DLL C++. Vous pouvez ensuite appeler ces classes wrapper. Je suis loin d'être un expert en la matière, mais je l'ai utilisé pour avoir accès aux méthodes win32 et à d'autres bibliothèques que j'avais besoin d'utiliser. Lien sur codeplex a quelques liens outils qui pourraient aider. Mais le plus important est probablement l'assistant Interop. Il peut générer les wrappers C# pour votre DLL C++.

Ce n'est pas exactement ce que vous demandez, mais j'ai pensé que cela pourrait aider à regarder une direction différente.

+0

Je n'ai jamais entendu parler de cet outil qui devrait beaucoup aider. J'espérais que le drapeau \ clr était magique ...: -/ – colithium