web-dev-qa-db-fra.com

Y a-t-il un moyen d'utiliser une API C ++ en C #?

Je souhaite coder un petit programme qui prend des données de suivi de la tête et déplace un objet 3D en conséquence à l'écran. Pour atteindre cet objectif, j'ai trouvé un logiciel appelé Opentrack qui a une API C++. Le problème est que tous les environnements de développement de jeu que je connaisse/ont un moyen d'accéder à l'utilisation C # comme langue.

Je suis très confortable avec C # et l'habitude d'être à l'aise avec C++ et C A pendant le dos et pourrait facilement y revenir si une solution l'avait requis.

Ceci est un petit projet personnel idiot, mais je suis passionné et aimerais résoudre, de sorte que toute aide pour résoudre ce problème soit appréciée. Merci!

METTRE À JOUR:

WOW, c'est une quantité incroyable et la qualité des réponses, je voudrais développer profondément tout le monde qui a contribué!

32
zoliking

Il existe différentes façons d'appeler le code natif de C #

  1. p/invoke - Permet aux appels de méthode de style C directement à partir du code C #. Si l'API n'expose pas les fonctions de style C (I.E. externe C), vous aurez besoin d'une enveloppe qui le fait. Si l'API utilise tout type d'objets, cela constituera probablement une approche douloureuse.
  2. C++/CLI - Cela vous permet d'utiliser des types .NET dans un projet C++. Vous créeriez donc un projet CARPPER C++ qui interface avec l'API Opentrack et s'appelle depuis votre code C # habituel. Cela ressemble à un bon guide sur la façon de faire cela. . Un avantage est qu'il vous permet d'écrire des emballages autour d'objets pour fournir une API orientée objet.
44
JonasH

Pour les API orientées objet, vous devez envisager d'utiliser un outil qui génère automatiquement un wrapper .NET. Vérifiez CPPSharp sur GitHub. Tout ne fonctionnera pas automatiquement, mais si vous allez envelopper 100 classes, il est logique de générer la majeure partie du code nécessaire à l'interopération.

Que vous n'alliez que d'envelopper quelques classes ou d'une liste de SDK entière et que vous écriviez votre propre code d'interopérabilité C++/CLI, il est toujours pratique de disposer du code C++/CLI dans un assemblage distinct puisque vous traiterez du code non géré et non géré. Débogage que vous souhaitez centraliser dans un seul composant.

12
helb

Vous pouvez sûr que vous pouvez, et je l'ai fait sur Windows et Mac à l'aide de .NET CORE 3.1, mais cela fonctionnera probablement avec la framework .NET ainsi que la modification minimale.

La méthode que j'ai utilisée est appelée DllImport _ et est décrit ici: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportattribute?View=NetFramework -4.8 # Exemples

Vous trouverez ci-dessous un exemple de mon propre code C #.

    class Program
    {
        // This is where you declare the functions from the C file that you want to use. The filename is a relative path to the file containing the `Program`
        [DllImport("libHello.dll")]
        static extern string say_hello(byte[] buffer);

        static void Main()
        {
             var buffer = new byte[1024]; // create byte buffer
             say_hello(buffer) // call the C function
             Console.WriteLine(Encoding.ASCII.GetString(buffer)) // 'hello'
        }

La partie la plus importante est de garantir que la bibliothèque C utilisée est compilée pour la plate-forme que vous utilisez.

Si vous revenez des données importantes dans le programme C #, vous pouvez penser à utiliser une bibliothèque appelée cJSON et en passant une structure C comme JSON sur le buffer, que vous pouvez alors désérialiser dans les cas de classe C #. C'est comme ça que je l'ai fait, et cela maintient vraiment la complexité C depuis que vous n'avez pas vraiment besoin de vous inquiéter de libérer de l'espace de tas du code C #.

Veuillez noter que j'ai accompli le ci-dessus en utilisant non-Microsoft Tooling pour le développement C (bien sûr, j'ai utilisé .NET CORE et CLI pour le C # Stuff). Je n'aime pas particulièrement Studio Visual C++ et c'est mon propre biais.

4

Swig - Wrapper et générateur simplifié est le seul moyen sain de faire des choses comme ceci. On dirait - CPPSharp mentionné par @Helb est construit sur le dessus. Alors allez pour CPPSharp, il n'est pas nécessaire de réinventer la roue.

Je souligne une colline, pas seulement pour la complétude, mais parce que, dans certains cas, il peut être plus simple. Je n'ai aucune expérience avec CPPSharp cependant.

Comme pour C++/CLI , je ne commencerai pas un nouveau projet avec elle. Pas même un projet "Hello World"! Je dis cela comme une personne qui a gaspillé une vie sur Microsoft Technologies comme WCF, WPF, Winforms, Odata et plus encore. Je me trompe peut-être mais je ne parierai tout simplement pas une pierre dessus. Oui, j'ai lu - this et je ne suis toujours pas convaincu que cela rendra la conclusion finale de .NET.

0
Saheed Bolarinwa