Pointeurs dans C # Unity

8

Hé, je viens de découvrir les pointeurs récemment et je me demande comment je peux les utiliser en c # (je viens de les découvrir en c ++) dans l'unité. J'ai cependant quelques questions.

  1. Les pointeurs utilisent une programmation de bas niveau pour trouver des positions de différentes valeurs sur l'ordinateur, cela signifie-t-il que vous pouvez simplement accéder à la valeur d'une variable à partir de n'importe quel script?
  2. Si c'est le cas, comment puis-je simplement invoquer l'emplacement d'une variable avec uniquement son code d'emplacement?
  3. Existe-t-il des différences perceptibles entre les pointeurs en C # et C ++ que je devrais connaître?
  4. Comment puis-je utiliser des pointeurs avec les types de variables dans Unity (Vector3s, Transforms, GameObjects, etc ...)?

Il y a tellement d'autres questions que je devrais probablement et voudrais poser si vous avez des informations ou des sources supplémentaires.

Ryan Henry
la source

Réponses:

6

En général pour C # et spécifiquement pour Unity, je le déconseille ... mais si vous le vouliez vraiment, ou si vous aviez de bonnes raisons, vous le pouviez.

En C #, vous devez vous familiariser avec ce qu'on appelle du code dangereux . Vous avez encore peur?

Dans Unity, vous devez activer le mode de compilation non sécurisé afin de ne pas pouvoir utiliser le lecteur Web si vous avez prévu cela. Vous pouvez en savoir plus ici ou ici .

Donc, fondamentalement, C # a été conçu avec un garbage collector comme le sont de nombreux langages de script. L'idée générale est d'essayer d'abstraire la notion de gestion de la mémoire pour simplifier le développement. Vous pouvez toujours vous retrouver avec des fuites de ressources si vous n'annulez pas vos objets. Je ne suis honnêtement pas un grand partisan des GC et préférerais plutôt les méthodes RAII , mais c'est le monde dans lequel nous vivons.

Cependant, la plupart des développeurs C ++ conviendraient également que vous ne devriez pas utiliser de pointeurs directement de toute façon et préféreriez utiliser un type conçu par RAII, c'est- à-dire des pointeurs intelligents . Si vous êtes en terre C, les pointeurs probables sont pour vous une seconde nature, mais même alors, cela aide à les abstraire dans une certaine mesure.

Si vous les utilisez en C #, sachez qu'il existe un potentiel très réel que vous pourriez ajouter des failles de sécurité ou vraiment méchant et difficile à traquer les bogues. Vous devrez également garder à l'esprit que vous devez faire attention à ne pas référencer les objets qui peuvent être déplacés par le GC. Notez l'utilisation de l'instruction fixe ici .

Vous pouvez également utiliser des pointeurs dans Unity en écrivant un plugin natif . Cela exclura à nouveau les versions de webplayer, mais la nouvelle fonctionnalité HTML5 fonctionne sur la base d' emscripten, donc si vous prévoyez de l'utiliser, vous le pourrez probablement si vous faites attention. Les plugins natifs vous permettent d'étendre Unity par plate-forme. J'ai écrit un plugin natif pour communiquer avec certains microcontrôleurs via une connexion série par exemple.

Donc, pour résumer, vous devriez certainement vous demander pourquoi je veux utiliser des pointeurs en C # dans Unity. Si vous voulez juste le faire pour le plaisir ... Assommez-vous.

Edit: Je suis désolé si j'avais offensé quelqu'un car je sais que mes pensées sur GC ne sont pas de l'opinion populaire en ce moment.

Si vous lisez vraiment ma réponse, vous remarquerez que je n'appelle pas C # un langage de script. Je le compare à "de nombreux langages de script", cependant, dans le contexte d'Unity, il est très utilisé comme langage de script. C'est un peu DSL pour Unity si vous voulez. Souvent, vous le verrez même appelé Unity Script dans ce contexte (c'est principalement en référence à l'alternative Javascript d'Unity à C #). Si vous mettez LLVM dans votre pipeline, vous pouvez simplement le compiler directement en code natif pour la plate-forme ... alors comment l'appelleriez-vous? Alors vraiment, je ne voulais pas couper les cheveux ici.

De nombreuses grandes références au génie logiciel sont remplies d'opinions:

C ++ efficace , plus efficace C ++ , C ++ FAQ , efficace C # , moderne C ++ Conception , Design Patterns ... Et tant d' autres. Je ne pense pas que cela rend les arguments moins crédibles s'ils sont suivis d'explications réfléchies.

Je ne disais pas vraiment "n'utilisez jamais de pointeurs !!" . En fait, je les utilise encore nus à l'occasion. J'ai dit "en général" comme dans "préfère utiliser un code sécurisé à un code non sécurisé en C #". Il y a des situations où cela peut être bénéfique, et c'est l'une des fonctionnalités vraiment puissantes de C # pour choisir vos outils. C # vous permet même d'avoir une certaine transparence dans le processus GC dans une certaine mesure, contrairement à des langages comme Dart et peut entraîner des fuites de ressources très facilement. Bien sûr, si vous êtes le seul développeur d'un petit projet, ce n'est probablement pas un problème. Si vous faites partie d'une équipe de 10+ avec des centaines de milliers de lignes de code, cela peut devenir difficile.

Je voulais simplement que le lecteur fasse preuve de prudence lorsqu'il utilise des pointeurs nus. Cela revient à dire soyez très prudent lorsque vous travaillez avec le réseau électrique. Je ne dis pas ne soyez pas électricien, juste que si vous faites le mauvais choix et ne le traitez pas avec respect, vous êtes mort.

J'aime l'exemple donné par Lasse dans lequel la performance peut avoir dicté le besoin.

Matthew Sanders
la source
1
C # n'est pas un langage de script, bien qu'il puisse être utilisé pour cela. Java a aussi un GC et ce n'est pas non plus un langage de script. Répondre à votre propre opinion sur ce qui est le mieux en général n'est pas la réponse objective que nous recherchons sur ce site. Dans un but spécifique, quelque chose comme du code et des pointeurs dangereux peut être très efficace.
Lasse
1
Je ne comprends pas pourquoi cette réponse est décotée - elle est très informative et montre beaucoup de recherches / connaissances et des liens vers d'autres lectures. Surtout pour @Lasse, qu'est - ce que le langage de script? Bien sûr, il serait plus précis de dire "langage utilisé pour les scripts dans l'unité", mais je ne vois pas beaucoup de raisons de revenir en arrière car Matthieu a omis 7 mots évidents et a utilisé un (sur) terme simplifié.
Wondra
@wondra J'ai voté parce que la réponse ne rend pas évident qu'il existe des endroits où les pointeurs peuvent très bien être utilisés en C #. Tout dépend de l'objectif et de la plate-forme cible. En fait, la réponse essaie d'effrayer tout le monde contre l'utilisation de pointeurs.
Lasse
1
@wondra Cette réponse ne répond guère à la question. Tout ce qu'il fait, c'est de ne pas utiliser de pointeurs. Cette section de commentaires n'est pas un endroit approprié pour en discuter. Vous pouvez rejoindre le chat si vous pensez avoir plus d'arguments.
Lasse
1
@Lasse ne peut pas vous convaincre et ce n'est pas mon combat, mais en voyant votre réponse - vous avez écrit exactement la même chose que cette réponse (qui a été publiée plus tôt), en plus vous n'avez même inclus qu'un sous-ensemble (= moins d'informations) sur le sujet comme cette réponse l'a fait.
wondra
6

C # utilise des références pour faire circuler des objets qui ne sont pas des types de valeur . Cela signifie que tout est généralement transmis par référence. Si vous souhaitez transmettre un type de valeur par référence, vous pouvez utiliser le mot clé ref . La différence entre un type de référence et un type de valeur est qu'en fonction de la taille du type de valeur, il nécessite généralement plus de mémoire copiée lorsqu'il est transmis à une fonction. Une référence ne fait que 32 bits ou 64 bits , ou 4 octets ou 8 octets. Vous pouvez obtenir plus de performances de votre code dans des boucles très serrées si vous utilisez des références au lieu de simplement copier toutes les données que contiennent les variables de type valeur, en supposant qu'elles dépassent 4 ou 8 octets.

Par exemple, sur Unity, tout objet MonoBehaviour (classe) est un type de référence et tout objet Vector3 (struct) est un type Value.

Il existe également des blocs de code dangereux qui vous permettront de taper du code qui vous permettra de créer et de modifier des données en toute sécurité. Pour utiliser du code dangereux, vous devrez configurer le compilateur pour autoriser le code dangereux. Les pointeurs peuvent être utilisés de cette façon. En utilisant du code non sécurisé, certaines vérifications ne sont pas utilisées avec du code sécurisé, ce qui rend le code non sécurisé plus difficile à écrire sans erreur. Il y a très peu d'endroits qui peuvent bénéficier d'un code dangereux sur C #. Sur Unity, le code non sécurisé n'est pas pris en charge sur toutes les plateformes. En général, l'utilisation de références au lieu de pointeurs non sécurisés suffit lorsque vous travaillez avec Unity.

Voici un exemple ( source ) d'utilisation de pointeurs de code non sécurisés en C # avec Unity:

public static class Rope
{
    // C# function declaration to match C++
    [DllImport(SlingshotImport.c_libName)]
    static unsafe extern void UpdateRopeParticlesUnsafe(
        Vector3* oldNew,
        Vector3* curr,
        int numParticles);

    // C# wrapper function for Unity C# script
    static void UpdateRopeParticles(
        Vector3[] oldNew,
        Vector3[] curr,
        int numParticles)
    {
        unsafe
        {
            fixed (Vector3* oldNewPtr = oldNew)
            fixed (Vector3* currPtr = curr)
            {
                UpdateRopeParticlesUnsafe(oldNewPtr, currPtr, numParticles);
            }
        }
    }
}
Lasse
la source
Je trouve intéressant que vous critiquiez ma réponse et que vous utilisiez les mêmes arguments, moins d'autres informations pertinentes, et que vous n'incluiez qu'une brève discussion des types valeur / référence. Vous pourriez au moins mentionner la boxe , les optimisations JIT qui pourraient parfois supprimer le surcoût de la copie du type de valeur, comment éviter les risques par le marshalling , ou peut-être que le code dangereux n'est pas toujours plus rapide que sûr
Matthew Sanders
Je suis désolé si vous vous sentez attaqué ou offensé. Ce n'était pas mon intention. J'ai critiqué votre réponse car elle me semblait très fondée sur l'opinion plutôt que sur les faits. J'ai fourni des réponses aux questions posées ainsi qu'un exemple de code. D'après votre réponse, je n'ai pas pu comprendre les choses que j'ai expliquées dans ma réponse, qui me paraissent plus pertinentes par rapport à la question posée. Je ne vois pas comment GC a quoi que ce soit à voir avec "comment utiliser les pointeurs?" ou je ne vous ai pas vu mentionner le fonctionnement des références sur C # car la question semblait supposer que les variables fonctionnaient de la même manière en C # et C ++.
Lasse
1
Pas de soucis. Merci pour vos excuses. J'ai mentionné le GC car vous devez être conscient que le passage de pointeurs vers des types gérés peut provoquer des problèmes si le GC déplace soudainement l'objet. J'ai supposé que le lecteur était au courant du système de type C # et de la façon dont les types référence vs valeur sont utilisés.
Matthew Sanders
Vous avez vraiment du mal à accepter une réponse. Vous m'avez tous les deux fourni toutes les informations nécessaires, je vais donc voter pour vous deux et accepter celle qui est venue en premier. Je ne veux rien dire par là. J'ai juste du mal à choisir et quant à me faire peur du "code dangereux" ne vous inquiétez pas. Je n'ai jamais été le seul à reculer devant un défi de toute façon. Bien que maintenant je sais que travailler avec des pointeurs n'est pas pratique en ce qui concerne le développement multiplateforme. Je tiens à vous remercier tous pour votre temps et vos opinions. et je suis désolé d'avoir commencé la Troisième Guerre mondiale, je n'ai pas voulu faire ça.
Ryan Henry