Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de DLL

Passage de fonction d'une dll C/C++ vers un programme C#

Sujet résolu
    31 mai 2021 à 18:16:37

    >J'ai déjà essayé avec des dé-compilateurs mais il ne me trouve rien

    Pouvez-vous nous envoyer l'assembly/Dll via un dépôt GitHub (ou autre) ?

    >Mon objectif est d'une part de comprendre le code

    De quel code s'agit-il ? Le code client de l'assembly ou le code de wrapping contenu/caché dans l'assembly/Dll SpinNET ?

    Le code .NET me semble assez clair, bien que mal adroit à quelques endroits. (donc une API avec une conception assez correcte)

    >et d'autre part de "le mettre à jour"

    Mais vous n'avez pas le code source de SpinNET, ou j'ai compris de travers ?

    >Je possède une en-tête qui regroupe (si j'ai bien regardé) toutes les autres en-têtes.

    OK, mais c'est pour du C++, vous n'avez pas besoin de ça si vous utilisez SpinNET.

    >incluant dans le .cpp, le nom de l'en-tête,

    Les .h ne contiennent pas le code, juste les déclarations des types et fonctions (à moins d'être un bibliothèque "header-only", mais j'en doute fortement).

    Pour utiliser le code binaire de la Dll, il faut faire des appels à ces fonctions/types dans votre code C++/CLI, ou plus difficilement/aléatoirement directement depuis du C#.

    >serait-il possible de retrouver leurs fonctions en C#

    Oui, mais c'est potentiellement très compliqué (fonction du compilateur C++ qui a généré la Dll Native, utilisation potentiel de pointeur intransferable directement en .NET, etc...). Tout cela n'existe pas si vous communiquez directement avec un assembly/Dll .NET.

    Je vous guide depuis le "début" sur la création de wrapper C++/CLI mais s'il existe déjà un assembly .NET, ces wrappers sont inutiles.

    Concrètement, c'est quoi les inputs de votre projet et les "limitations/évolutions" que vous devez 'faire sauter/implémenter" ???

    • Partager sur Facebook
    • Partager sur Twitter
    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
      1 juin 2021 à 8:55:34

      Pour résumé, je possède des bibliothèques, en-têtes avec une version 3.3. J'ai trouvé sur internet un sdk avec la version 3.0 (include, librairie, dll, fichier debug), mon but est de réussir à coder avec les fichiers du 3.3 sans dépendre du sdk.
      • Partager sur Facebook
      • Partager sur Twitter
        1 juin 2021 à 11:46:39

        OK.

        Question con, vous êtes sûr que cette bibliothèque n'est pas en Open Source ?

        La version 3.0 contient un assembly .NET, donc ? Vous êtes sûr que la version 3.3 n'en dispose pas ?

        Une assembly .NET, ça n'a pas besoin de .h ou d'un SDK pour être directement utilisable dans un autre projet/exécutable (c'est l'un des gros avantages de .NET).

        Pouvez-vous nous communiquer les fichiers de la version 3.3 (via GitHub ou autre) ?

        Avant de faire des "bridges" qui correspondent aux classes du SDK, je vous conseille de faire quelques wrappers des classes de la version 3.3.

        Contrairement aux bridges, les wrappers se résument à beaucoup de copier-coller, comme mon exemple de code précédemment posté.

        • Partager sur Facebook
        • Partager sur Twitter
        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
          1 juin 2021 à 12:48:21

          Pour avoir accès au code source, il faut un abonnement.

          Voici tout les fichiers qui va avec la version 3.3 (il faut dézipper dans le dossier implémentation en fonction de votre ordinateur) dans le lien ci-dessous:

          https://www.emva.org/wp-content/uploads/GenICam_Package_2021.02.zip

          merci pour votre investissent dans mon problème

          -
          Edité par VincentL10 1 juin 2021 à 12:48:52

          • Partager sur Facebook
          • Partager sur Twitter
            3 juin 2021 à 0:38:22

            >Pour avoir accès au code source, il faut un abonnement.

            A plusieurs centaine d'€ par jour la prestation d'un développeur, l'abonnement est très vite rentabilisé, mais bon.

            OK, c'est pas vraiment plus clair mais c'est du concret.

            Avant d'aller plus loin. Si je comprends bien, vous cherchez à avoir une API C# identique ou proche de celle de SpinNET mais en utilisant la version 3.3 de GenICam. Si le packaging de SpinNet est bien fait et qu'il n'y a pas de problème de rétro-compatibilité (ce que doit indiquer le 3 de 3.0 et de 3.3), il est tout à fait possible que cet assembly .NET s'upgrade "tout seul" (via fichier de configuration, fichier de patching dans le GAC, etc...).

            Avez-vous compulsé la documentation de cet assembly sur les différents paramétrages qu'il support ?

            Il est peut-être possible d'upgrader SpinNet sans la moindre ligne de code (donc moins de boulot et moins de bug).

            Même si SpinNET n'est pas packagé pour s'upgrader, il est assez probable qu'il soit désassemblable et que la mise à niveau des sources ne demanderait que de très faibles modification par rapport à tout reprendre from scratch.

            Je n'ai pas vu de "GC.h" que vous nous avez posté dans ce sujet. Le zip est vaste et il contient lui-même des zip dans tout les coins. Ca ne facilite pas la recherche. Je n'ai fait que jeter un coup d’œil rapide au contenu du zip car lire la documentation prendrait beaucoup de temps. (J'ai quand même vu des ponts vers JAVA et Python, ce qui serait peut-être plus simple que le C++ si vous connaissez bien l'un de ces 2 langages.)

            Mais j'ai rapidement eu accès à 3 .h qui me semblent être l'API "de départ" : PFNC.H, GenDC.h et GenTL.h.

            Si vous voyez des .h plus pertinents, faites le moi savoir.

            (EDIT: après avoir regardé l'ensemble des .dll, il est clair que vous devriez faire un recensement de celles-ci et de faire un graphe de dépendance entre elles et de récupérer le ou les .h correspondant au niveau d'abstraction que vous voulez récupérer déduit de ce graphe)

            Clairement, l'API de GenICam (basée sur ma vue des 3 fichiers .h) est loin d'être aussi "conviviale" que celle de SpinNET.

            Il y a 2 voix pour completer ce gap. Soit vous êtes à laisse en C++/CLI et vous faites les bridges directement en C++, soit vous êtes plus à laisse en .NET et vous ne faite que des wrappers en C++/CLI et vous implémenter les bridges en .NET en s'appuyant sur ces wrappers.

            Vous devriez cherchez la Dll permettant d'avoir le moins de travail entre son API et votre API cible (SpinNET ?).

            Exemple de récupération dans du code C++/CLI du contenu de ces 3 .h :

            PFNC.H est un header de "bas niveau" (utilisé par les autres) et ne définit qu'un monceau de constantes, un enum et déclare+defini(inline) 2 fonctions libres "utilitaires" (pas besoin du moindre .lib ou .dll pour s'en servir, c'est une espèce de bibliothèque "header only"). Soit vous en avez besoin que dans le code C++ (implémentation de bridge) et dans ce cas, juste l'inclure dans le .cpp qui l'utilise suffit. Si vous voulez que du code .NET puisse accéder à ces constantes/enum/fonction libre, il faudra un peu plus de travail.

            Pour que les constantes à base de #define et les enum soient visible en .NET facilement, il faut un peu ruser :

            https://www.techtalkz.com/threads/exposing-a-c-enum-in-a-managed-c-assembly.67089/#post283183

            https://stackoverflow.com/questions/3240263/sharing-an-enum-from-c-c-cli-and-c

            Pour la conversion entre .NET et Natif :

            https://docs.microsoft.com/fr-fr/cpp/dotnet/how-to-define-and-consume-enums-in-cpp-cli?view=msvc-160

            Pour ce qui est des 2 fonctions libres, comme elles utilisent des pointeurs et des classes natives dans leur signature, le plus simple, c'est de faire un wrappers vite fait :

            #undef _MANAGED
            #include "PFNC.h"
            
            #define _MANAGED
            namespace GENAPI_NAMESPACE_Wrappers
            {
            #include "PFNC.h"
            
                public ref class PFNC abstract sealed
                {
                    public static System::String^ GetPixelFormatName(PfncFormat format)
                    {
                        return marshal_as(::GetPixelFormatName((int)format));
                    }
            
                    public static System::String^ GetPixelFormatDescription (PfncFormat format)
                    {
                        return marshal_as(::GetPixelFormatDescription ((int)format));
                    }
                }
            }

            GenDC.H, c'est un peu le même topo que PFNC.h, donc les mêmes astuces pour les #define et les enum. Il y a pas mal de typedef que les mécanismes d'alias de .NET permettent "d'émuler". Les structures et les unions sont des POCO sans aucun comportement, donc aussi facile à "émuler" (si nécessaire). L'équivalent des template C++, c'est les génériques .NET. Comme PFNC.h, pas besoin du moindre .lib ou .dll pour s'en servir, c'est une espèce de bibliothèque "header only".

            GenTL.h est, lui, est un vrai header "chapeau" d'une Dll. Il permet d'utiliser les fonctions libres implémentées dans une Dll. A partir de la ligne 695, il spécifie l'API C (pas C++, même si ce fichier n'est utilisable qu'avec un compilateur C++), de la Dll et vous pouvez faire la même tambouille que pour les fonctions libre de PFNC.h. Les ruses pour les #define, les enum ... fonctionneront aussi bien dans ce cas de figures.

            Donc, en résumé, faire le graphe des Dll, voir les .h chapeaux de ces Dll pour vérifier le niveau d'abstraction exportée par cette Dll (en commençant par le plus haut niveau, la Dll qui dépend de toutes les autres). Le but est d'utiliser l'API (Dll) ayant le plus de point commun avec l'API C# que vous cherchez à reproduire, pour minimiser le travail d'implémentation des bridges.

            Une fois la Dll/.h choisi, il "suffit" de faire le même travail de carrossage du contenu du .h pour qu'il soit utilisable depuis .NET, si on fait les bridges en .NET, soit juste inclure simplement le .h et implémenté les bridges .NET directement en C++/CLI.

            • Partager sur Facebook
            • Partager sur Twitter
            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
              3 juin 2021 à 9:03:30

              Pour faire clairement ça, j'ai recommencé depuis le début.

              Changer juste les dll semblent compliquer (pas dans le remplacement des fichiers) mais du fait que les dll utiliser dans le SpinNET utiliser des version debug.

              Je me suis pencher tout d'abord sur le GenTl et j'ai trouvé ca:

              #include <iostream>
              #include <sstream>
              
              #include <_GenICamVersion.h>
              #include <GenICam.h>
              #include <GenICamFwd.h>
              #include <GenICamVersion.h>
              
              #include <GenApi/GenApi.h>
              
              #include <CLProtocol/CLProtocol.h>
              #include <CLProtocol/CLPort.h>
              
              #include <FirmwareUpdate/FirmwareUpdater.h>
              
              #include "GenTL.h"
              #include "GenDC.h"
              #include "PFNC.h"
              
              
              using namespace GENAPI_NAMESPACE;
              using namespace GENICAM_NAMESPACE;
              using namespace GenApi_3_3;
              using namespace GenApi;
              using namespace GenTL;
              
              using namespace std;
              
              //Main
              int main() {
              	GCInitLib();										//Initialize GenTL Producer
              	TL_HANDLE hTL = OpenTL();							//Retrieve TL Handle
              	IF_HANDLE hIface = OpenFirstInterface(hTL);			//Retrieve first Interface Handle
              	DEV_HANDLE hDevice = OpenFirstDevice(hIface);		//Retrieve first Device Handle
              	DS_HANDLE hStream = OpenFirstDataStream(hDevice);	//Retrieve first Data Stream
              
              	CloseDataStream(hStream);							//Close Data Stream
              	CloseDevice(hDevice);								//Close Device
              	CloseInterface(hIface);								//Close Interface
              	CloseTL(hTL);										//Close System module
              	GCCloseLib();										//Shutdown GenTL Producer
              
              }
              
              TL_HANDLE OpenTL( void )
              {
              	TLOpen(hTL);	
              }
              
              IF_HANDLE OpenFirstInterface(hTL)
              {
              	TLUpdateInterfaceList(hTL);
              	TLGetNumInterfaces(hTL, NumInterfaces);
              	if (NumInterfaces > 0)
              	{
              		// First query the buffer size
              		TLGetInterfaceID(hTL, 0, IfaceID, &bufferSize);
              		// Open interface with index 0
              		TLOpenInterface(hTL, IfaceID, hNewIface);
              
              		return hNewIface;
              	}
              }
              
              DEV_HANDLE OpenFirstDevice(hIF)
              {
              	IFUpdateDeviceList(hIF);
              	IFGetNumDevices(hTL, NumDevices);
              	if (NumDevices > 0)
              	{
              		// First query the buffer size
              		IFGetDeviceID(hIF, 0, DeviceID, &bufferSize);
              		// Open interface with index 0
              		IFOpenDevice(hIF, DeviceID, hNewDevice);
              		return hNewDevice;
              	}
              }
              
              DS_HANDLE OpenFirstDataStream(hDev)
              {
              	// Retrieve the number of Data Stream
              	DevGetNumDataStreams(hDev, NumStreams);
              
              	if (NumStreams > 0)
              	{
              		// Get ID of first stream using
              		DevGetDataStreamID(hdev, 0, StreamID, buffersize);
              		// Instantiate Data Stream
              		DevOpenDataStream(hDev, StreamID, hNewStream);
              	}
              }
              
              void CloseDataStream(hStream)
              {
              	DSClose(hStream);
              }
              
              void CloseDevice(hDevice)
              {
              	DevClose(hDevice);
              }
              
              void CloseInterface(hIface)
              {
              	IFClose(hIface);
              }
              
              void CloseTL(hTL)
              {
              	TLClose(hTL);
              }
              
              
              	

              Plusieurs variables me sont revenus comme non défini.

              Passer par un wrapper m'a l'air plutot pas mal.

              J'ai également trouver un wrapper.hh dans les fichiers

              #ifndef _LOG4CPP_WRAPPER_HH
              #define _LOG4CPP_WRAPPER_HH
              
              #include <log4cpp/Category.hh>
              #include <log4cpp/NDC.hh>
              #include <log4cpp/PatternLayout.hh>
              #include <log4cpp/PropertyConfigurator.hh>
              #if defined (_WIN32)
              #include <log4cpp/Win32DebugAppender.hh>
              #endif
              
              LOG4CPP_NS_BEGIN
              //! A function table which is bound to log4cpp's Category class
              typedef struct {
                  Category& (*getInstance)(const std::string& name);
                  std::vector<Category*>* (*getCurrentCategories)();
                  Category* (*exists)(const std::string& name);
                  Category& (*getRoot)();
                  void(*shutdown)();
                  void (Category::*logva)(Priority::Value priority, const char* stringFormat, va_list va);
                  bool (Category::*isInfoEnabled)();
                  bool (Category::*isWarnEnabled)();
                  bool (Category::*isDebugEnabled)();
                  void (Category::*setPriority)(Priority::Value priority);
                  void (Category::*addAppender)(Appender* appender);
                  void (Category::*removeAppender)(Appender* appender);
              } category_t;
              
              //! A function table which is bound to log4cpp's PatternLayout class
              typedef struct {
                  PatternLayout* (*create)();
                  void (PatternLayout::*setConversionPattern)(const std::string& conversionPattern);
                  void(*destroy)(PatternLayout* object);
              } pattern_layout_t;
              
              //! A function table which is bound to log4cpp's PropertyConfigurator class
              typedef struct {
                  void(*configure)(std::istream& initStream);
              } property_configurator_t;
              
              //! A function table which is bound to log4cpp's NDC class
              typedef struct {
                  void(*push)(const std::string& message);
                  std::string(*pop)();
              } ndc_t;
              
              #if defined (_WIN32)
              //! A function table which is bound to log4cpp's Win32DebugAppender class
              typedef struct {
                  Appender *(*create)(const std::string& name);
              } win32_debug_appender_t;
              #endif
              
              //! A function table which is bound to log4cpp's Appender class
              typedef struct {
                  Appender *(*createFileAppender)(const std::string& name, const std::string& fileName, bool append, mode_t mode);
                  void (Appender::*setThreshold)(Priority::Value threshold);
                  void (Appender::*setLayout)(Layout* layout);
              } appender_t;
              
              //! A wrapper which bridges to log4cpp functionality.
              typedef struct {
                  category_t Category;
                  pattern_layout_t PatternLayout;
                  property_configurator_t PropertyConfigurator;
                  ndc_t NDC;
              #if defined (_WIN32)
                  win32_debug_appender_t Win32DebugAppender;
              #endif
                  appender_t Appender;
              } wrapper_t;
              
              //! A functionality wrapper (= a set of function tables) which is exported.
              extern "C" LOG4CPP_EXPORT const LOG4CPP_NS::wrapper_t Wrapper;
              LOG4CPP_NS_END
              
              #endif // _LOG4CPP_WRAPPER_HH
              

              J'ai trouvé cela : https://docs.microsoft.com/fr-fr/cpp/dotnet/how-to-wrap-native-class-for-use-by-csharp?view=msvc-160




              -
              Edité par VincentL10 3 juin 2021 à 9:40:38

              • Partager sur Facebook
              • Partager sur Twitter
                3 juin 2021 à 12:27:34

                "wrapper.hh", c'est juste un .h qui permet d'utiliser plus facilement Log4cpp, qui est un framework de "log" pour le C++, donc n'a pas vraiment d'intérêt pour le "bridging" .NET (à moins de vouloir que le code Natif et .NET log dans les mêmes fichiers au même format, mais bon).

                Pour "GenTl", c'est clairement un code foireux par l'usage complètement incohérent de putatives variables globales. Si ces énormes erreurs ne vous semblent pas évidentes, pensez à revoir un peu le codage en C++ avant de continuer plus avant.

                Malgré ses énormes erreurs (et lourdeur) ce code, il peut montrer un designe d'API .NET très facile à faire à partir de l'API C utilisée dans ce code.

                Un truc du genre :

                public ref class GenTL_Producer
                {
                    public TL_Handle^ th;
                
                    public GenTL_Producer()
                    {
                        GCInitLib();
                        th = gcnew TL_Handle(this);
                    }
                
                    public ~GenTL_Producer()
                    {
                        delete th;
                        GCCloseLib();
                    }
                }
                
                public ref class TL_Handle
                {
                    private GenTL_Producer^ gp;
                    public Interface_Handle^ ih;
                    internal TL_HANDLE handle;
                
                    public TL_Handle(GenTL_Producer gp_)
                    {
                        gp = gp_;
                        OpenTL(handle);
                        ih = gcnew Interface_Handle(this);
                    }
                
                    public ~TL_Handle()
                    {
                        delete ih;
                        CloseTL(handle);
                    }
                }
                
                public ref class Interface_Handle
                {
                    private Device_Handle^ dh;
                    public TL_Handle^ th;
                    internal IF_HANDLE handle;
                
                    public Interface_Handle(TL_Handle^ th_)
                    {
                        th = th_;
                        handle = OpenFirstInterface(th.handle);
                        dh = gcnew Device_Handle(this);
                    }
                
                    public ~Interface_Handle()
                    {
                        delete dh;
                        CloseInterface(handle);
                    }
                }
                
                public ref class Device_Handle
                {
                    private Data_Stream^ ds;
                    public Interface_Handle^ ih;
                    internal DEV_HANDLE handle;
                
                    public Device_Handle(Interface_Handle^ ih_)
                    {
                        ih = ih_;
                        handle = OpenFirstDevice(ih.handle);
                        ds = gcnew Data_Stream(this);
                    }
                
                    public ~Device_Handle()
                    {
                        delete ds;
                        CloseDevice(handle);
                    }
                }
                
                public ref class Data_Stream
                {
                    private Device_Handle^ dh;
                    private DS_HANDLE handle;
                
                    public Data_Stream(Device_Handle^ dh_)
                    {
                        dh = dh_;
                        handle = OpenFirstDataStream(dh.handle);
                    }
                
                    public ~Data_Stream()
                    {
                        CloseDataStream(handle);
                    }
                }

                Juste en instanciant "GenTL_Producer" (pensez à implémenter un DP type Singleton), vous disposez de l'ensemble des objets de l'API Native accessible depuis du code .NET.

                Ici, on a fait qu'"objectiser" l'API C pour quelle soit utilisable en .NET.

                >les dll utiliser dans le SpinNET utiliser des version debug.

                Mais si vous avez le code source de SpinNET, le plus simple, c'est de faire quelques modifications dans le paramétrage de génération, voire faire quelques modifications/ajout pour utiliser les nouvelles fonctionnalités de la version 3.3 du package.

                • Partager sur Facebook
                • Partager sur Twitter
                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                  3 juin 2021 à 12:51:37

                  Le code pour le genTl est un exemple de leur documation

                  Pour le spinNET, j'ai accès à leurs en-têtes, dll et quelques exemples.

                  Est ce que instancier les headers principaux serviraient à le rendre accessible au code .NET ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 juin 2021 à 15:35:47

                    >Le code pour le genTl est un exemple de leur documation

                    Peut-être, mais c'est quand même tout pourri et c'est tout à fait normal que cela ne compile pas.

                    Je problème n'est pas chez vous mais dans le code source lui-même.

                    On comprend l'idée du bidule, mais c'est vraiment implémenté n'importe comment.

                    >j'ai accès à leurs en-têtes

                    C'est pas un assembly .NET ? Si oui, il n'y pas besoin de fichiers d'en-tête.

                    A moins qu'il implémente une double API, une native et une .NET.

                    Si vous avez les Dll, on peut toujours voir si elles sont désassemblables.

                    >Est ce que instancier les headers principaux

                    Qu'entendez-vous pas "instancier un header" ?

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                      3 juin 2021 à 15:48:40

                      Je possède les en-têtes et dll + librairie et en plus je possède des dll (sans leur code source) qui utilisent dans leurs programmes (leurs exemples).

                      Le sdk possède 2 librairies un CPP et un DotNET.

                      Instancier des headers comme Gentl_Producer pour l'objectiser pour qu'elle soit utilisable

                      • Partager sur Facebook
                      • Partager sur Twitter
                        3 juin 2021 à 17:19:59

                        >Je possède les en-têtes et dll + librairie

                        J'ai du mal à savoir si vous parlez du package GenICam ou de SpinNet.

                        >qui utilisent dans leurs programmes (leurs exemples).

                        Leurs codes d'exemples doivent avoir un bien meilleur code que celui de leur documentation.

                        >Le sdk possède 2 librairies un CPP et un DotNET.

                        DotNET ? Un assembly managé, avec le source ? c'est SpinNet ou GenICam  ?

                        >Instancier des headers comme Gentl_Producer

                        Gentl_Producer n'est pas header, c'est une classe managée (c'est à cela que sert le "ref" devant class).

                        Et les classes managée sont utilisable par tout langage .NET, du moment qu'il référence l'assembly qui export cette classe managée.

                        Il est donc tout à fait possible de faire un "Gentl_Producer gp = new Gentl_Producer();" dans un code C#.

                        -
                        Edité par bacelar 3 juin 2021 à 18:36:21

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                          3 juin 2021 à 17:30:47

                          Excuser moi de mes imprécisions, Je possède les en-têtes et dll + librairie,  comprend les deux packages.

                          DotNET ? Un assembly managé, avec le source ? c'est SpinNet ou GenICam  ? Cela correspond seulement au SpinNet.

                          Leurs codes d'exemples doivent avoir un bien meilleur code que celui de leur documentation. En effet, le code pour le contrôle de la caméra est plutôt clair mais il utilise une Dll dont je n'ai pas accès à leur contenu (sauf via "trouver la définition", mais pour refaire ce dernier il me manque trop d'éléments). (Leur exemple ne marche que dans leur package. Je n'ai pas réussit à en refaire un à l'identique pour essayer (bien sur en réutilisant leur dll déjà faite).

                          • Partager sur Facebook
                          • Partager sur Twitter
                            3 juin 2021 à 18:37:49

                            Bon, pouvez-vous m'envoyer la Dll .NET, les header, et un code source d'un de leur utilitaire ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                              17 juin 2021 à 9:52:42

                              Je m'en occupe dès que possible.

                              Je dois réaliser un programme qu'avec Genicam. J'ai donc créer un cpp regroupant (quasi) toutes les fonctions des en-têtes fournis et j'ai repris un programme d'exécution en cs pour faire les essais. Je rencontre un problème dans mon programme cs, j'appelle une classe INodeMap que j'instancie par le mot nodeMap et j'essaye d'utiliser la fonction GetNode, mais il ne la reconnait pas. 

                              INodeMap.h

                              GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap
                                  {
                                      virtual INode* GetNode( const GENICAM_NAMESPACE::gcstring& Name) const = 0;
                                  }

                              Dans mon cpp qui génère une dll

                              public class INodeMap
                              {
                                    INode* GetNode(gcstring& Name);
                              }

                              Dans mon .cs

                              int AcquirePic(INodeMap nodeMap)
                              {
                                  INodeMap iAquiMode = nodeMap.GetNode("AquisitionMode");
                              ...
                              
                              }

                              Pouvez-vous m'aider ou est-il préférable que je dépose les dossiers ?

                              Pour les dossiers souhaiter vous celui de Spin, Genicam ou les deux ?

                               Je peux mettre les dll, les header et si par code source vous parlez de .cpp, je n'en ai pas (sauf celui que j'ai créé donc surement avec des erreurs)

                              Merci par avance



                              • Partager sur Facebook
                              • Partager sur Twitter
                                18 juin 2021 à 15:50:49

                                >Je dois réaliser un programme qu'avec Genicam.

                                C'est quoi ces contraintes à la con ?

                                Votre wrapper C++/CLI, il sera tout aussi .NET et "en plus" que SpinNET.

                                Faudrait pas se mettre des bâtons dans les roues pour que dal.

                                Avoir le code de SpinNet (via desassemblage ou pas) permettrait d'avoir des exemples concrets.

                                La déclaration dans le .h, c'est juste la déclaration d'une interface C++, "utilisable" quand C++, et encore, par directement (il faut des classes dérivées et des API C++ qui l'utilise).

                                Ce n'est donc "utilisable" que dans une implémentation de wrapper C++/CLI, pas dans du code C#.

                                Le code C++, c'est juste une déclaration d'une classe native (qui n'entre pas en collision de nom avec la déclaration dans le .h grace vraisemblablement à un espace de nom judicieusement planqué dans la MACRO "GENICAM_INTERFACE" ). C'est donc tout aussi inutilisable en C# que l'interface déclarée dans le .h.

                                Vos classes wrapper devraient être des classes .NET/managée (public ref class Toto {...}).

                                https://docs.microsoft.com/fr-fr/cpp/dotnet/how-to-define-and-consume-classes-and-structs-cpp-cli?view=msvc-160

                                Et n'utilisez pas des pointeurs dans l'API (champs, propriétés, types de retour de méthodes, paramètres de méthodes) publiée par vos classes managées, si elles doivent être appelable depuis du C#.

                                Dans votre code C#, il y une incohérence frappante.

                                Si la méthode "GetNode" renvoie un INode* ( et non un INodeMap ou un INodeMap*) pourquoi voulez-vous qu'il en soit autrement en C# ? Pourquoi "iAquiMode" est un INodeMap et pas un INode ???

                                Donc, un bout de code pour commencer les wrappers .NET (j'ai utilisé un suffixe "W" et non un namespace pour que la distinction natif/managé soit plus "lisible"):

                                public ref class INodeW
                                {
                                }
                                
                                public ref class INodeMapW
                                {
                                      GENICAM_INTERFACE GENAPI_DECLABSTRACT INodeMap* nativeINodeMap = null;
                                
                                public :
                                      INodeW^ GetNode(String^ Name)
                                      {
                                           //ici la tambouille pour convertir une String^ en gstring "name_"
                                
                                           GENICAM_INTERFACE GENAPI_DECLABSTRACT INode* p_node = nativeINodeMap(name_);
                                
                                           //ici la tambouille pour créer un InodeW nodeWrapper, à partir d'un INode* p_node, par exemple en le passant en paramètre du constructeur d'un InodeW 
                                
                                           return nodeWrapper;
                                      }
                                }

                                Les détails comme comment initialiser le champ "nativeINodeMap" de l'instance de classe INodeMapW, etc... c'est fonction de comment est conçu l'API native et comment vous comptez concevoir l'API managée.

                                >Pour les dossiers souhaiter vous celui de Spin, Genicam ou les deux ?

                                Mettez tout dans un dépôt Git, on fera le tri plus tard.

                                -
                                Edité par bacelar 21 juin 2021 à 20:52:15

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                  21 juin 2021 à 9:05:49

                                  iAquiMode est un INodeMap car la fonction qu'il utilise fait parti de l'en-tête INodeMap et non INode. Merci pour ce bout de code, je vois où j'ai fauté dans la classe.

                                  Puis-je savoir pourquoi la fonction de création d'objet est égale à "null" ?

                                  Je m'occupe des dossiers dès que je peux.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    21 juin 2021 à 20:56:59

                                    >iAquiMode est un INodeMap car la fonction qu'il utilise fait parti de l'en-tête INodeMap et non INode.

                                    Et ?

                                    L'endroit où une fonction est utilisée ou déclarée ou définie n'indique en rien le type d'une variable ou du type de retour d'une fonction.

                                    C'est la ligne de déclaration de la variable ou de la fonction qui indique leur type (et leur définition doivent correspondre à cette déclaration).

                                    >Puis-je savoir pourquoi la fonction de création d'objet est égale à "null" ?

                                    Oups, le mélange de code C++ natif et managé ne me réussit pas. C'est "__nullptr" qu'il utiliser.

                                    Ce n'est pas une "fonction de création d'objet" mais la déclaration d'un champ privé à la classe .NET INodeMapW.

                                    Le but d'un wrapper est "d'enrober" un objet natif par une enveloppe utilisable en managé. L'instance de la classe INodeMapW est l'enveloppe et son champ "nativeINodeMap" est l'objet natif qui est enveloppé.

                                    Comme je ne connais pas le pattern de création implémenté par l'API native (constructeur "classique" (très peu probable), singleton, factory, etc...), j'ai fait au plus simple. Vous devez initialiser ce champ avec l'objet natif et l'utilisation de cette valeur permet de facilement détecter des erreurs de type valeurs non initialisées.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                      22 juin 2021 à 9:04:35

                                      Voici ce que j'ai fait mais une erreur persiste, la E0109 sur le morceau nativeINodeMap(name_)

                                      "l'expression qui précède les parenthèses de l'appel apparent doit avoir le type defonction (pointeur-à-)"

                                      //Wrapper.cpp
                                      
                                      #include <string>
                                      #include <iostream>
                                      #include <vcclr.h>
                                      
                                      #include "pch.h"
                                      #include "EnTete.h" //En-tête Genicam
                                      
                                      //Raccouci d'appel
                                      using namespace GENAPI_NAMESPACE;
                                      using namespace GENICAM_NAMESPACE;
                                      using namespace std;		//MarshalString
                                      using namespace System;		//MarshalString
                                      
                                      // Wraper
                                      namespace WrapperNET
                                      {
                                      	//Sous-partie Wrapper
                                      	namespace GenApi
                                      	{
                                      		//INode
                                      		public ref class Node
                                      		{
                                      			//Création d'objet de la classe INode
                                      			GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * nativeINode = __nullptr;
                                      		};
                                      
                                      		//INodeMap
                                      		public ref class NodeMap
                                      		{
                                      			//Création d'objet de la classe INodeMap
                                      			GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap * nativeINodeMap = __nullptr;
                                      		public:
                                      
                                      			//Retrieves the node from the central map by Name
                                      			Node^ GetNode(String^ Name)
                                      			{
                                      
                                      				//Converstion gcstring en String^ et de Name en name_
                                      				gcstring name_;
                                      				String^ iName = gcnew String(name_.c_str());
                                      
                                      				GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * p_node = nativeINodeMap(name_);
                                      
                                      				//Création de nodeWrapper
                                      				Node ^ nodeWrapper(INode * p_node);
                                      
                                      				//Retour de la fonction GetNode
                                      				return nodeWrapper(p_node);
                                      			}
                                      		};
                                      	}
                                      }
                                      

                                      Est ce que cela vous semble juste ?

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        22 juin 2021 à 13:19:15

                                        >une erreur persiste, la E0109

                                        Comme je l'ai déjà indiqué, "nativeINodeMap" n'est pas une fonction/functor/lambda mais un simple champ (pour "nativeINode", c'est pareil). Ce n'est pas un moyen de créer l'objet qu'il référence. cf. "pattern de création" de mon post précédent.

                                        Attention au ' " include "pch.h" ', ligne 7, normalement, vous devriez le mettre au tout début du fichier, et mettre dans le fichier pch.h les #include de tous les fichiers communs à tous les .cpp (<string> ?, <vcclr.h> ?, etc...). C'est juste pour l'optimisation du temps de compilation, pas très grave pour l'instant.

                                        Ligne 40 à 42, c'est presque l'inverse qu'il faut faire. Le code .NET appelant la méthode GetNode passe une String^ en paramètre. Vous devez la convertir en gcstring pour appeler la fonction native "GetNode" de l'objet référencé dans le champ "nativeINodeMap".

                                        En gros, à l'arrache, si on considère que l'INodeMap se récupère via un Singleton, ça donnerait un code un peu comme celui qui suit (pas thread-safe, etc...) :

                                        //Wrapper.cpp 
                                        #include "pch.h"
                                        
                                        #include "EnTete.h" //En-tête Genicam
                                        
                                        #include <string>
                                        #include <iostream>
                                        #include <vcclr.h>
                                        
                                        //Raccouci d'appel
                                        using namespace GENAPI_NAMESPACE;
                                        using namespace GENICAM_NAMESPACE;
                                        using namespace std;        //MarshalString
                                        using namespace System;     //MarshalString
                                         
                                        // Wraper
                                        namespace WrapperNET
                                        {
                                            internal gcstring NetString2gcstring(String^ name)
                                            {
                                                gcstring retval{};
                                        
                                                // Les bidouilles avec MarshalString pour remplir "retval" avec le contenu de "name"
                                        
                                                return retval;
                                            }
                                        
                                            //Sous-partie Wrapper
                                            namespace GenApi
                                            {
                                                //INode
                                                public ref class Node
                                                {
                                                    GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * nativeINode = __nullptr;
                                        
                                                    //Peut-être plus pertinent d'utiliser une référence ou un smart-pointer à la place d'un pointeur "nu"
                                                    //Et d'utiliser la liste d'initialisation que le corps du constructeur
                                                    //à vérifier la compatibilité avec une classe managée
                                                    Node(GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * nativeINode_)
                                                    {
                                                        nativeINode = nativeINode_;
                                                    }
                                                };
                                         
                                                //INodeMap
                                                public ref class NodeMap
                                                {
                                                    GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap * nativeINodeMap = __nullptr;
                                        
                                                    bool CheckNativeSingleton()
                                                    {
                                                        if(nativeINodeMap == __nullptr)
                                                        {
                                                            nativeINodeMap = GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap::GetInstance();
                                                        }
                                        
                                                        return (nativeINodeMap != __nullptr);
                                                    }
                                        
                                                public:
                                         
                                                    //Retrieves the node from the central map by Name
                                                    Node^ GetNode(String^ Name)
                                                    {
                                                        if(CheckNativeSingleton())
                                                        {
                                                            GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * p_node = nativeINodeMap.GetNode(NetString2gcstring(Name));
                                         
                                                            if(p_node != __nullptr)
                                                            {
                                                                //Création de nodeWrapper
                                                                Node^ nodeWrapper = gcnew Node(p_node);
                                         
                                                                //Retour de la fonction GetNode
                                                                return nodeWrapper;
                                                            }
                                                            else
                                                            {
                                                                throw .... //fonction de comment vous voulez que le code .NET gère les erreurs Runtime
                                                            }
                                                        }
                                                        else
                                                        {
                                                            throw .... //fonction de comment vous voulez que le code .NET gère les erreurs Runtime
                                                        }
                                                    }
                                                };
                                            }
                                        }



                                        -
                                        Edité par bacelar 22 juin 2021 à 13:20:41

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                          22 juin 2021 à 14:01:54

                                          Merci, je vais regarder cela. d'ou vient le INodeMap:: GetInstance(); Je ne le trouve pas et le return nodeWrapper; ne marche pas comme ca, il me le met en erreur. Pour MarshalString J'ai deux fonctions, je vais essayer de les retrouver.

                                          J'ai trouvé que les classes abstraites ne sont pas instanciable mais que les fonctions pures le sont (J'y arrive pas totalement encore).

                                          Visual studio ne reconnait pas internal.

                                          -
                                          Edité par VincentL10 22 juin 2021 à 14:04:30

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            22 juin 2021 à 15:02:52

                                            >d'ou vient le INodeMap:: GetInstance()

                                            C'est mon hypothèse de départ : "l'INodeMap se récupère via un Singleton"

                                            Une manière "classique" d'implémenter un Singleton, c'est de créer une fonction statique "GetInstance" qui retourne l'unique instance de la classe (cf. le Design Pattern Singleton).

                                            Si vous avez un code C++ natif d'exemple qui créer/récupérer une instance d'INodeMap, montrez-le nous, on trouvera facilement le Design Pattern de création que ce code utilise.

                                            Le plus simple, c'est que vos wrappers utilisent les mêmes Design Pattern de création que le code C++ natif.

                                            >que les classes abstraites ne sont pas instanciable

                                            C'est la définition même du classe abstraite, c'est aussi pour cela que je parle des Design Pattern de création utilisés car vous ne pouvez pas simplement instancier une de ces classes pour en avoir une instance. D'où mon hypothèse d'un singleton, mais ça peut être une fonction "factory", une suite d'appel "builder", etc... . Le plus simple, comme déjà écrit ci-avant, donnez-nous un exemple "C++ Natif" qui fonctionne, on trouvera facilement quel Design Pattern de création est en action.

                                            >mais que les fonctions pures le sont

                                            ??? Une "fonction", en terme strict, ça ne s'instancie pas, contrairement à des functor, donc je ne sais pas de quoi vous parler.

                                            Vous voulez dire "appelable" ?

                                            Si oui, c'est normal, c'est le "contrat" que donne l'interface, toute classe "instanciable" qui implémente l'interface s'engage à implémenter toutes ces fonctions virtuelle pure, sinon, elle n'est pas instanciable et cela sera uniquement les classes dérivées qui les implémentent toutes qui seront instanciables.

                                            Pour "internal", enlevez-le. Normalement, c'est la valeur par défaut, mais il y a peut-être un peu de subtilité que je n'ai plus en tête.

                                            -
                                            Edité par bacelar 22 juin 2021 à 15:05:09

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                              22 juin 2021 à 15:22:11

                                              //INodeMap.h
                                              
                                              #ifndef GENAPI_INODEMAP_H
                                              #define GENAPI_INODEMAP_H
                                              
                                              #include <Base/GCBase.h>
                                              #include <GenApi/INode.h>
                                              #include <GenApi/IPort.h>
                                              #include <GenApi/IPortStacked.h>
                                              #include <GenApi/Synch.h>
                                              #include <GenApi/ConcatenatedWrite.h>
                                              
                                              #ifdef _MSC_VER
                                              #   pragma warning ( push )
                                              #   pragma warning ( disable : 4251 ) // XXX needs to have dll-interface to be used by clients of class YYY
                                              #endif
                                              
                                              namespace GENAPI_NAMESPACE
                                              {
                                              
                                                  //*************************************************************
                                                  // INodeMap interface
                                                  //*************************************************************
                                              
                                                  /**
                                                  \brief Interface to access the node map
                                                  \ingroup GenApi_PublicInterface
                                                  */
                                                  GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap
                                                  {
                                                      //! Retrieves all nodes in the node map
                                                      virtual void GetNodes(NodeList_t &Nodes) const =  0;
                                              
                                                      //! Retrieves the node from the central map by Name
                                                      virtual INode* GetNode( const GENICAM_NAMESPACE::gcstring& Name) const = 0;
                                              
                                                      //! Invalidates all nodes
                                                      virtual void InvalidateNodes() const =  0;
                                              
                                                      //! Connects a port to a port node with given name
                                                      virtual bool Connect( IPort* pPort, const GENICAM_NAMESPACE::gcstring& PortName) const = 0;
                                              
                                                      //! Connects a port to the standard port "Device"
                                                      virtual bool Connect( IPort* pPort) const = 0;
                                              
                                                      //! Connects a port to a port node with given name
                                                      virtual bool Connect(IPortStacked* pPort, const GENICAM_NAMESPACE::gcstring& PortName) = 0;
                                              
                                                      //! Connects a port to the standard port "Device"
                                                      virtual bool Connect(IPortStacked* pPort) = 0;
                                              
                                                      //! Get device name
                                                      /*! The device name identifies a device instance, e.g. for debugging purposes.
                                                      The default ist "Device". */
                                                      virtual GENICAM_NAMESPACE::gcstring GetDeviceName() = 0;
                                              
                                                      //! Fires nodes which have a polling time
                                                      virtual void Poll( int64_t ElapsedTime ) = 0;
                                              
                                                      //! Returns the lock which guards the node map
                                                      virtual CLock& GetLock() const = 0;
                                              
                                                      //! Get the number of nodes in the map
                                                      virtual uint64_t GetNumNodes() const  = 0;
                                              
                                                      //! Parse all Swissknife equations
                                                      virtual bool ParseSwissKnifes( GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL ) const = 0;
                                              
                                                      //! Create a new write concatenator object
                                                      virtual CNodeWriteConcatenator *NewNodeWriteConcatenator() const = 0;
                                              
                                                      //! Execute the transaction
                                                      virtual bool ConcatenatedWrite(CNodeWriteConcatenator *, bool featureStreaming = true, GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL) = 0;
                                              
                                                  };
                                              }
                                              
                                              #ifdef _MSC_VER
                                              #   pragma warning ( pop )
                                              #endif
                                              
                                              #endif // ifndef GENAPI_INODEMAP_H
                                              Voici le INodeMap.h.
                                              Je pense que le GetInstance() équivaut au InvalidateNodes() ?
                                              //Wrapper.cpp
                                              #include "pch.h"
                                              
                                              #include "EnTete.h" //En-tête Genicam
                                              
                                              #include <string>
                                              #include <iostream>
                                              #include <vcclr.h>
                                              
                                              //Raccouci d'appel
                                              using namespace GENAPI_NAMESPACE;
                                              using namespace GENICAM_NAMESPACE;
                                              using namespace std;        //MarshalString
                                              using namespace System;     //MarshalString
                                              using namespace Runtime::InteropServices;
                                              
                                              // Wrapper
                                              namespace WrapperNET
                                              {
                                              	gcstring NetString2gcstring(String^ name)
                                              	{
                                              		gcstring retval{};
                                              
                                              		const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(name)).ToPointer();
                                              		retval = chars;
                                              		Marshal::FreeHGlobal(IntPtr((void*)chars));
                                              		
                                              
                                              		return retval;
                                              	}
                                              
                                              	//Sous-partie Wrapper
                                              	namespace GenApi
                                              	{
                                              		//INode
                                              		public ref class Node
                                              		{
                                              			GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * nativeINode = __nullptr;
                                              
                                              			//Peut-être plus pertinent d'utiliser une référence ou un smart-pointer à la place d'un pointeur "nu"
                                              			//Et d'utiliser la liste d'initialisation que le corps du constructeur
                                              			//à vérifier la compatibilité avec une classe managée
                                              			Node(GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * nativeINode_)
                                              			{
                                              				nativeINode = nativeINode_;
                                              			}
                                              		};
                                              
                                              		//INodeMap
                                              		public ref class NodeMap
                                              		{
                                              			GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap * nativeINodeMap = __nullptr;
                                              
                                              			bool CheckNativeSingleton()
                                              			{
                                              				if (nativeINodeMap == __nullptr)
                                              				{
                                              					nativeINodeMap = GENAPI_DECL_ABSTRACT INodeMap::GetInstance();
                                              				}
                                              
                                              				return (nativeINodeMap != __nullptr);
                                              			}
                                              
                                              		public:
                                              
                                              			//Retrieves the node from the central map by Name
                                              			Node^ GetNode(String^ Name)
                                              			{
                                              				if (CheckNativeSingleton())
                                              				{
                                              					GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * p_node = nativeINodeMap.GetNode(NetString2gcstring(Name));
                                              
                                              					if (p_node != __nullptr)
                                              					{
                                              						//Création de nodeWrapper
                                              						Node^ nodeWrapper = gcnew Node(p_node);
                                              
                                              						//Retour de la fonction GetNode
                                              						return nodeWrapper;
                                              					} 
                                              /*					else
                                              					{
                                              						throw .... //fonction de comment vous voulez que le code .NET gère les erreurs Runtime
                                              
                                              					}
                                              */				} 
                                              /*				else
                                              				{
                                              					throw ....//fonction de comment vous voulez que le code .NET gère les erreurs Runtime
                                              				}
                                              */			};
                                              		};
                                              	}
                                              }
                                              
                                              Erreurs :
                                              GetInstance() > pas de membre
                                              nativeINodeMap de nativeINodeMap.GetNode(NetString... > l'expression doit avoir un type de classe
                                              A Node^ nodeWrapper = gcnew Node(p_node) > il indique qu'il est inacessible
                                              Je suis en train de voir pour le NetString2gcstring il est très probablement faux.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                22 juin 2021 à 16:23:58

                                                >Voici le INodeMap.h.

                                                Je ne vous demande pas la déclaration complète de l'interface, je vous demande un exemple d'utilisation de cette interface.

                                                Ca doit trainer dans la documentation ou dans des projets d'exemple du SDK.

                                                >Je pense que le GetInstance() équivaut au InvalidateNodes() ?

                                                WTF ?!?

                                                GetInstance, ça demande une instance d'une classe, donc c'est une fonction statique.

                                                InvalidateNodes, c'est marqué dans les commentaires juste au dessus, c'est une méthode (fonction d'instance virtuelle si vous préférez) invalide les nœuds ce cette Map (captain obvious).

                                                Avant de faire des Wrappers .NET il faut maîtriser un minimum l'API Native du bidule.

                                                Ligne 25, vous êtes sûr que la classe "GENICAM_NAMESPACE::gcstring" copie bien le contenu de la chaîne en interne lors d'une affectation depuis un "const char *" ??? Parce que vous supprimez/désallouez/libérez ce pointeur ligne 26. Si c'est pas le cas, vous allez faire planté votre programme.

                                                >GetInstance() > pas de membre

                                                Je le répète pour la n-ième fois, il faut adapter le code au Design Pattern de création de l'API Native.

                                                >nativeINodeMap de nativeINodeMap.GetNode(NetString... >

                                                Faudrait avoir le message d'erreur complet, SVP.

                                                Mais comme il y a ces cochonneries de MACRO qui trainent, je remplacerais les lignes suivantes, pour ne pas avoir d'ambiguïté d'interprétation du "*" des pointeurs "nu" :

                                                Ligne 36 par :

                                                GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode* nativeINode = __nullptr;

                                                Ligne 52 par :

                                                 GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap* nativeINodeMap = __nullptr;

                                                >A Node^ nodeWrapper = gcnew Node(p_node) >

                                                Oups, un petit "public" à ajouter ligne 43 :

                                                public Node(GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode* nativeINode_)





                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                  22 juin 2021 à 16:53:49

                                                  Le nativeINodeMap est souligné rouge, Erreur E0153, l'expression doit avoir un type de classe

                                                  GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * p_node = nativeINodeMap.GetNode(NetString2gcstring(Name));

                                                  Voici une partie du programme en CSharp : avec le premier appel:

                                                  static int AcqImg(IManagedCamera cam, INodeMap nodeMap) //IManagedCamera propre au sdk
                                                          {
                                                              int result = 0;
                                                  
                                                              try
                                                              {
                                                                  IEnum iAcquisitionMode = nodeMap.GetNode<IEnum>("AcquisitionMode"); //IEnum, interface fille de IValue, SDK
                                                                  if (iAcquisitionMode == null || !iAcquisitionMode.IsWritable) //INode pour le IsWritable (inline bool)
                                                                  {
                                                                      Console.WriteLine("Unable to set acquisition mode to continuous (node retrieval). Aborting...\n");
                                                                      return -1;
                                                                  }
                                                  
                                                              ...

                                                  Pour la ligne 26, j'indique d'abord le return avant de décharger ?

                                                  -
                                                  Edité par VincentL10 22 juin 2021 à 16:59:01

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    22 juin 2021 à 19:00:08

                                                    >Le nativeINodeMap est souligné rouge, Erreur E0153

                                                    Compilez, SVP, les "souligné rouge", c'est la compilation en tâche de fond : ce n'est pas fiable et leur numéro d'erreur ne sont pas correctement référencées.

                                                    Et mettez systématiquement le "*" des pointeurs collé au nom du type :

                                                    GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode * p_node = nativeINodeMap.GetNode(NetString2gcstring(Name));
                                                    

                                                    devient 

                                                    GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode* p_node = nativeINodeMap.GetNode(NetString2gcstring(Name));
                                                    

                                                    >Voici une partie du programme en CSharp : avec le premier appel:

                                                    Je vous demande un code d'exemple en C++ Natif et vous me fournissez un code CSharp ?!?!?

                                                    D'une, les Design Pattern de création peuvent être tout à fait différent entre ces 2 API : la .NET et la native ; de 2, si vous avez du code CSharp qui fait le taf, c'est que vous avez déjà des wrappers .NET et qu'on se fait chier POUR RIEN !!!

                                                    Le code CSharp montre que l'interface .NET INodeMap est assez proche (mais pas identique) à celle correspondant à l'interface INodeMap native.

                                                    L'API .NET et bien plus stricte niveau typage car "GetNode" n'est pas utilisé mais "GetNode<IEnum>" qui semble utiliser un type "IEnum" bien plus spécialisé que "INode". C'est du typage "générique" .NET avec coté C++ Natif des choses approchantes comme les templates. Vérifiez coté C++ Natif si vous n'avez pas ces interfaces "templatisées" permettant un bien meilleur typage.

                                                    En en revient à POURQUOI VOUS N'UTILISEZ PAS CES PUTAINS D'ASSEMBLIES .NET QUE VOUS AVEZ DÉJÀ ??? (Et qui semble bien mieux que cette API Native toute moisie !!!)

                                                    Le code que vous nous donnez UTILISE un INodeMap, nous, il nous faut savoir comment est créé (cf. Design Pattern de création) le paramètre "nodeMap" de la méthode "AcqImg". Mais si vous regardez dans les codes d'exemple en CSharp, vous aurez le Design Pattern de création en .NET, pas celui en C++ Natif.

                                                    Donc, essayez de trouver un exemple de création d'une classe dérivant de INodeMap, en C++ Natif, pour voir comment c'est censé être créé. Vous pouvez aussi voir un exemple d'utilisation de la méthode "GetNode", en C++ Natif, et remonter les appels pour revenir au point de création du paramètre "nodeMap" de "GetNode".

                                                    >Pour la ligne 26, j'indique d'abord le return avant de décharger ?

                                                    ???

                                                    Vous ne pouvez rien faire après un return.

                                                    Il faut s'assurer que gcstring soit le propriétaire (l'ownership des informations, ici les octets contenant les codes ASCIIs de la chaîne de caractère).

                                                    Le plus simple, c'est de regarder le code source de l'opérateur d'affectation de la classe gcstring prenant un "const char*" en paramètre et de voir s'il copie la contenu de la chaîne ou pas. (C'est de l'Open Source, c'est fait pour ça.)(Après, il y a la documentation des classes, mais vous semblez un peu trop perdu en C++ pour la comprendre, non ?)

                                                    S'il n'est pas propriétaire, la mémoire contenant la chaîne de caractère peut être allouée à autre chose à n'importe quel moment, ce qui potentiellement est catastrophique.

                                                    En C++, vous devez maîtriser qui est propriétaire de la mémoire et beaucoup de fonctionnalités récentes du C++ permettent de facilement gérer cela. Mais une classe qui accept directement une affectation depuis un pointeur nu comme un "const char*", c'est que c'est du vieux code casse-gueule et qu'il faut donc vérifier qu'ils ont fait correctement les choses.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                      23 juin 2021 à 8:58:00

                                                      Puis-je savoir pourquoi faut-il mettre le "*" du côté du type ?

                                                      Ou puis-je trouver le code C++ Natif, s'il correspond à un code source cpp, je n'ai qu'un exemple d’exécution en c++ et cs.

                                                      Je souhaiterais coder cela de manière indépendante.

                                                      //Conversion de String en gcstring
                                                      	gcstring NetString2gcstring(String^ name)
                                                      	{
                                                      		String^ managed = name;
                                                      		gcstring retval = msclr::interop::marshal_as<gcstring>(managed);
                                                      		
                                                      		return retval;
                                                      	}

                                                      Voici ce que j'ai trouvé pour le String to gcstring (Je crois que j'ai inversé)

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        23 juin 2021 à 10:16:18

                                                        >Puis-je savoir pourquoi faut-il mettre le "*" du côté du type ?

                                                        En C, puis en C++, l'astérisque "*" qui indique l'usage d'un pointeur "nu", chose très déconseillée en C++ depuis la norme C++11 (2011).

                                                        Mais cet astérisque doit, lors d'une déclaration/définition de variable, pour ne pas le confondre avec l'opérateur/opération "multiplication", soit être collé à la fin du type de la variable, soit au début du nom de la variable.

                                                        Donc, ça c'est OK :

                                                        char* c1;
                                                        char *c2;

                                                        Mais, ça, si ça compile, c'est un UB (Undefined Behaviour)

                                                        char * c3;


                                                        >je n'ai qu'un exemple d’exécution en c++

                                                        Montrez-le nous.

                                                        >Je souhaiterais coder cela de manière indépendante.

                                                        Indépendante de quoi ???

                                                        Pour le code suivant, plus simple, ne fonctionnerait pas ? :

                                                            gcstring NetString2gcstring(String^ name)
                                                            {
                                                                gcstring retval = msclr::interop::marshal_as<gcstring>(name);
                                                                 
                                                                return retval;
                                                            }

                                                        Si "msclr::interop::marshal_as<gcstring>" fait en sorte de copier les données sans une zone "safe", elle le ferait aussi bien, que la variable passée en paramètre soit une variable locale ou une variable "paramètre".

                                                        .NET a un système "d'internalisation" des chaînes de caractère qui est très particulier, donc ne pas utiliser des choses qui sont censées fonctionner avec d'autres types et les transposer sur des String^.


                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                          23 juin 2021 à 10:51:53

                                                          Voici la même fonction mais en c++:

                                                          int AcqImg(CameraPtr pCam, INodeMap& nodeMap, INodeMap& nodeMapTLDevice) //CameraPtr propre au SDK
                                                          {
                                                              int result = 0;
                                                          
                                                              try
                                                              {
                                                                  CEnumerationPtr ptrAcquisitionMode = nodeMap.GetNode("AcquisitionMode");
                                                                  if (!IsAvailable(ptrAcquisitionMode) || !IsWritable(ptrAcquisitionMode))
                                                                  {
                                                                      cout << "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." << endl << endl;
                                                                      return -1;
                                                                  }
                                                          	...

                                                          La compilation plante à cause de la conversion

                                                          error C4996: 'msclr::interop::error_reporting_helper<_To_Type,_From_Type,false>::marshal_as': This conversion is not supported by the library or the header file needed for this conversion is not included.  Please refer to the documentation on 'How to: Extend the Marshaling Library' for adding your own marshaling method.
                                                          1>        with
                                                          1>        [
                                                          1>            _To_Type=GIC_3_3::gcstring,
                                                          1>            _From_Type=System::String ^
                                                          1>        ]

                                                          Je vais revoir ca

                                                          -
                                                          Edité par VincentL10 23 juin 2021 à 10:52:55

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            23 juin 2021 à 12:01:10

                                                            Ok, ça commence à prendre forme.

                                                            Le code C++ est assez similaire au code C# sans être identique.

                                                            C'est assez bizarre que le code C# n'ait besoin que d'un paramètre "INodeMap" et que la version C++ en ait besoin de 2.

                                                            Mais comme on n'a pas le corps de la fonction en entier, c'est peut-être normal.

                                                            Il faut que vous remontiez l'appel de la fonction "AcqImg" dans le code C++ pour voir comment ses paramètres "nodeMap" et "nodeMapTLDevice" sont construits dans la fonction appelante, ou dans la fonction appelante de la fonction appelante si ils sont eux même des paramètres de la fonction appelante, et ainsi de suite, juste qu'à trouver le code qui "instancie" ces paramètres. (Mais bon, normalement, les Design Pattern de création, ils devraient être dans la documentation du bidule).

                                                            Vos wrapper C++/CLI .NET devront utiliser les mêmes Design Pattern de création que ceux trouvés dans le code C++ Natif.

                                                            La ligne 7 du code C++ semble montrer que le code C++ Natif n'utilise pas les mécanismes de template directement, mais un mécanisme bien plus spécifique à Windows, les CComPtr.

                                                            Si le type "CEnumerationPtr" derive ou contient, directement ou indirectement un CComPtr ( https://docs.microsoft.com/fr-fr/cpp/atl/reference/ccomptr-class?view=msvc-160 ), nous seront fasse à une API COM et donc qu'on s'enquiquine à faire des wrappers .NET alors que les composants COM qui semblent utilisés par le code C++ Natif SONT DIRECTEMENT UTILISABLE EN .NET !!!

                                                            Ne nous auriez-vous pas "caché" des informations/exports de Dll ???

                                                            Si c'est le cas, ça fait donc plus de 3 mois qu'on tourne en rond pour rien ?

                                                            Pouvez-vous nous donner la déclaration de la classe "CEnumerationPtr" ?

                                                            A noter que si c'est bien un CComPtr, le Design Pattern de création devrait être très spécifique à ce type de pointeurs.

                                                            Pour "msclr::interop::marshal_as<gcstring>" :

                                                            https://docs.microsoft.com/fr-fr/cpp/dotnet/how-to-extend-the-marshaling-library?view=msvc-160

                                                            Mais vous devez comprendre comment fonctionne gcstring en interne car ce n'est vraisemblablement pas un simple char*.

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                              23 juin 2021 à 13:01:47

                                                              Après quelques modifications, je programme compile et la fonction getNode est disponible et reconnue en C#. Merci beaucoup pour votre aide.

                                                              //Wrapper.cpp
                                                              #include "pch.h"
                                                              #include <string>
                                                              
                                                              #include "EnTete.h"					//En-tête Genicam
                                                              #include <msclr/marshal_cppstd.h>	//NetString2gcstring
                                                              #include <msclr/marshal.h>
                                                              #include <vcruntime_exception.h>	//Exception
                                                              
                                                              //Raccouci d'appel
                                                              using namespace GENAPI_NAMESPACE;
                                                              using namespace GENICAM_NAMESPACE;
                                                              using namespace System;
                                                              using namespace Runtime::InteropServices;
                                                              using namespace std;
                                                              
                                                              
                                                              // Wrapper
                                                              namespace WrapperNET
                                                              {
                                                              	//Conversion de String en gcstring
                                                              	gcstring NetString2gcstring(String^ name)
                                                              	{
                                                              		const char* cstr = (const char*)(Marshal::StringToHGlobalAnsi(name)).ToPointer();
                                                              		gcstring retval = cstr;
                                                              		Marshal::FreeHGlobal(IntPtr((void*)cstr));
                                                              
                                                              		return retval;
                                                              	}
                                                              
                                                              	//Sous-partie Wrapper
                                                              	namespace GenApi
                                                              	{
                                                              		//INode
                                                              		public ref class Node
                                                              		{
                                                              			GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode* nativeINode = __nullptr;
                                                              
                                                              		public:
                                                              			Node(GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode* nativeINode_)
                                                              			{
                                                              				nativeINode = nativeINode_;
                                                              			}
                                                              		};
                                                              
                                                              		//INodeMap
                                                              		public ref class NodeMap
                                                              		{
                                                              			GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INodeMap* nativeINodeMap = __nullptr;
                                                              
                                                              			bool CheckNativeSingleton()
                                                              			{
                                                              				if (nativeINodeMap == __nullptr)
                                                              				{
                                                              					//nativeINodeMap = GENAPI_DECL_ABSTRACT INodeMap::GetInterface();
                                                              				}
                                                              
                                                              				return (nativeINodeMap != __nullptr);
                                                              			}
                                                              
                                                              		public:
                                                              
                                                              			//Retrieves the node from the central map by Name
                                                              			Node^ GetNode(String^ Name)
                                                              			{
                                                              				if (CheckNativeSingleton())
                                                              				{
                                                              					GENICAM_INTERFACE GENAPI_DECL_ABSTRACT INode* p_node = nativeINodeMap->GetNode(NetString2gcstring(Name));
                                                              
                                                              					if (p_node != __nullptr)
                                                              					{
                                                              						//Création de nodeWrapper
                                                              						Node^ nodeWrapper = gcnew Node(p_node);
                                                              
                                                              						//Retour de la fonction GetNode
                                                              						return nodeWrapper;
                                                              					}
                                                              					else
                                                              					{
                                                              						exception e;
                                                              						cout << "Error: " << e.what() << endl;
                                                              					}
                                                              				}
                                                              				else
                                                              				{
                                                              					exception e;
                                                              					cout << "Error: " << e.what() << endl;
                                                              				}
                                                              			};
                                                              		};
                                                              	}
                                                              }
                                                              

                                                              Par rapport au C++ et Cs, il y a bien deux paramètres à chaque, "nodeMap" et "nodeMapTLDevice".

                                                              Je viens de le trouver dans le programme Cpp du SDK.

                                                              SystemPtr system = System::GetInstance();

                                                              Voici comment il est appelé mais dans une autre fonction qui quant à elle se trouve être appelé dans le main

                                                               result = result | AcquireImages(pCam, nodeMap, nodeMapTLDevice);


                                                              Pointer.h (en rapport à CEnumerationPtr):

                                                              #ifndef GENAPI_POINTER_H
                                                              #define GENAPI_POINTER_H
                                                              
                                                              #include <assert.h>
                                                              #include <GenICamFwd.h>
                                                              #include <GenApi/IEnumeration.h>
                                                              #include <GenApi/IFloat.h>
                                                              #include <GenApi/IInteger.h>
                                                              
                                                              namespace GENAPI_NAMESPACE
                                                              {
                                                                  //*************************************************************
                                                                  // CPointer class
                                                                  //*************************************************************
                                                              
                                                                  /**
                                                                  \brief Encapsulates a GenApi pointer dealing with the dynamic_cast automatically
                                                                  \ingroup GenApi_PublicUtilities
                                                                  */
                                                                  template <class T, class B = IBase>
                                                                  class CPointer
                                                                  {
                                                              
                                                                  public:
                                                                      //! Default constructor.
                                                                      CPointer(void) throw()
                                                                          : m_pT( NULL )
                                                                      {
                                                                      }
                                                              
                                                                      //! Constructor from INode pointer type.
                                                                      CPointer( B *pB )
                                                                          : m_pT( dynamic_cast<T*>(pB) )
                                                                      {
                                                                      }
                                                              
                                                                      virtual ~CPointer(void)
                                                                      {
                                                                      }
                                                              
                                                                      //! Assign INode Pointer
                                                                      void operator=( B *pB )
                                                                      {
                                                                          m_pT = dynamic_cast<T*>(pB);
                                                                      }
                                                              
                                                                      //! Dereferencing
                                                                      operator T*(void) const
                                                                      {
                                                                          if (NULL == m_pT)
                                                                              throw LOGICAL_ERROR_EXCEPTION( "NULL pointer dereferenced" );
                                                                          return m_pT;
                                                                      }
                                                              
                                                                      //! Dereferencing
                                                                      T& operator*(void) const
                                                                      {
                                                                          if (NULL == m_pT)
                                                                              throw LOGICAL_ERROR_EXCEPTION( "NULL pointer dereferenced" );
                                                                          return *m_pT;
                                                                      }
                                                              
                                                                      //! Dereferencing
                                                                      T& operator()(void) const
                                                                      {
                                                                          if (NULL == m_pT)
                                                                              throw LOGICAL_ERROR_EXCEPTION( "NULL pointer dereferenced" );
                                                                          return *m_pT;
                                                                      }
                                                              
                                                                      //! Dereferencing
                                                                      T* operator->(void) const
                                                                      {
                                                                          if (NULL == m_pT)
                                                                              throw LOGICAL_ERROR_EXCEPTION( "NULL pointer dereferenced" );
                                                                          return m_pT;
                                                                      }
                                                              
                                                                      //! true if the pointer is valid
                                                                      bool IsValid() const throw()
                                                                      {
                                                                          return m_pT != NULL;
                                                                      }
                                                              
                                                                      //! true if the pointer is valid
                                                                      operator bool(void) const throw()
                                                                      {
                                                                          return m_pT != NULL;
                                                                      }
                                                              
                                                                      //! pointer equal
                                                                      bool operator==(T* pT) const 
                                                                      {
                                                                          return m_pT == pT;
                                                                      }
                                                              
                                                                      //! pointer equal
                                                                      bool operator==(const CPointer<T,B> &rT) const 
                                                                      {
                                                                          return m_pT == rT.m_pT;
                                                                      }
                                                              
                                                                      //! pointer equal
                                                                      bool operator==(int nMustBeNull) const
                                                                      {
                                                                          if (0 != nMustBeNull)
                                                                              throw LOGICAL_ERROR_EXCEPTION( "argument must be NULL" );
                                                                          return NULL == m_pT;
                                                                      }
                                                              
                                                              
                                                                  protected:
                                                              
                                                                      //! Underlying raw pointer.
                                                                      T* m_pT;
                                                                  };
                                                              
                                                                  //*************************************************************
                                                                  // Smartpointer for all interface
                                                                  //*************************************************************
                                                              
                                                                  //! \addtogroup GenApi_PublicUtilities
                                                                  //! \{
                                                              
                                                                  //! SmartPointer for IBase interface pointer
                                                                  typedef CPointer<IBase> CBasePtr;
                                                              
                                                                  //! SmartPointer for INode interface pointer
                                                                  typedef CPointer<INode> CNodePtr;
                                                              
                                                                  //! SmartPointer for IValue interface pointer
                                                                  typedef CPointer<IValue> CValuePtr;
                                                              
                                                                  //! SmartPointer for ICategory interface pointer
                                                                  typedef CPointer<ICategory> CCategoryPtr;
                                                              
                                                                  //! SmartPointer for IBoolean interface pointer
                                                                  typedef CPointer<IBoolean> CBooleanPtr;
                                                              
                                                                  //! SmartPointer for IInteger interface pointer
                                                                  typedef CPointer<IInteger> CIntegerPtr;
                                                              
                                                                  //! SmartPointer for IString interface pointer
                                                                  typedef CPointer<IString> CStringPtr;
                                                              
                                                                  //! SmartPointer for IRegister interface pointer
                                                                  typedef CPointer<IRegister> CRegisterPtr;
                                                              
                                                                  //! SmartPointer for IEnumeration interface pointer
                                                                  typedef CPointer<IEnumeration> CEnumerationPtr;
                                                              
                                                                  //! SmartPointer for IEnumEntry interface pointer
                                                                  typedef CPointer<IEnumEntry> CEnumEntryPtr;
                                                              
                                                                  //! SmartPointer for IPort interface pointer
                                                                  typedef CPointer<IPort> CPortPtr;
                                                              
                                                                  //! SmartPointer for IPortReplay interface pointer
                                                                  typedef CPointer<IPortReplay> CPortReplayPtr;
                                                              
                                                                  //! SmartPointer for IPortRecorder interface pointer
                                                                  typedef CPointer<IPortRecorder> CPortRecorderPtr;
                                                              
                                                                  //! SmartPointer for IPortWriteList interface pointer
                                                                  typedef CPointer<IPortWriteList, IPortWriteList> CPortWriteListPtr;
                                                              
                                                                  //! SmartPointer for IChunkPort interface pointer
                                                                  typedef CPointer<IChunkPort> CChunkPortPtr;
                                                              
                                                                  //! SmartPointer for INodeMap interface pointer
                                                                  typedef CPointer<INodeMap, INodeMap> CNodeMapPtr;
                                                              
                                                                  //! SmartPointer for IDeviceInfo interface pointer
                                                                  typedef CPointer<IDeviceInfo, INodeMap> CDeviceInfoPtr;
                                                              
                                                                  //! SmartPointer for IUserData interface pointer
                                                                  typedef CPointer<IUserData, INodeMap> CNodeMapUserDataPtr;
                                                                  //! SmartPointer for IUserData interface pointer
                                                                  typedef CPointer<IUserData> CNodeUserDataPtr;
                                                              
                                                                  //! SmartPointer for ISelector interface pointer
                                                                  typedef CPointer<ISelector> CSelectorPtr;
                                                              
                                                                  //! SmartPointer for ICommand interface pointer
                                                                   typedef CPointer<ICommand> CCommandPtr;
                                                              
                                                                   //! SmartPointer for IFloat interface pointer
                                                                  class CFloatPtr : public CPointer<IFloat, IBase>
                                                                  {
                                                                  public:
                                                                      //! Default constructor.
                                                                      CFloatPtr() throw()
                                                                          : CPointer<IFloat, IBase>(  )
                                                                      {
                                                                      }
                                                              
                                                                      //! Constructor from IBase pointer type.
                                                                      CFloatPtr( IBase *pB )
                                                                          : CPointer<IFloat, IBase>( pB )
                                                                      {
                                                                      }
                                                              
                                                                      //! Assign IBase Pointer
                                                                      void operator=( IBase *pB )
                                                                      {
                                                                          CPointer<IFloat, IBase>::operator =(pB);
                                                                      }
                                                              
                                                                      //! gets the interface of an integer alias node.
                                                                      IInteger *GetIntAlias()
                                                                      {
                                                                          return dynamic_cast<IInteger*>(m_pT->GetNode()->GetCastAlias());
                                                                      }
                                                              
                                                                      //! gets the interface of an enum alias node.
                                                                      IEnumeration *GetEnumAlias()
                                                                      {
                                                                          return dynamic_cast<IEnumeration*>(m_pT->GetNode()->GetCastAlias());
                                                                      }
                                                                  };
                                                              
                                                                  //! \}
                                                              
                                                                  //! \addtogroup GenApi_PublicImpl
                                                                  //! \{
                                                              
                                                                  //! SmartPointer for IPortConstruct interface pointer
                                                                  typedef CPointer<IPortConstruct> CPortConstructPtr;
                                                              
                                                                  //! SmartPointer for IPortStackedConstruct interface pointer
                                                                  typedef CPointer<IPortStackedConstruct> CPortStackedConstructPtr;
                                                              
                                                                  //! Returns the name of the main interface as string
                                                                  //! DEPRECATED, use IBase::GetPrincipalInterfaceType() instead
                                                                  inline GENICAM_NAMESPACE::gcstring GetInterfaceName(IBase *pBase)
                                                                  {
                                                              #       ifdef _MSC_VER
                                                              #           pragma warning (push) // icc -W4 complains: controlling expression is constant
                                                              #           pragma warning (disable : 279)
                                                              #       endif
                                                                      assert(pBase && "don't call this with a NULL pointer");
                                                              #       ifdef _MSC_VER
                                                              #           pragma warning (pop)
                                                              #       endif
                                                                      CNodePtr ptrNode(pBase);
                                                                      switch(ptrNode->GetPrincipalInterfaceType())
                                                                      {
                                                                      case intfIValue:
                                                                          return GENICAM_NAMESPACE::gcstring("IValue");
                                                                      case intfIInteger:
                                                                          return GENICAM_NAMESPACE::gcstring("IInteger");
                                                                      case intfIBoolean:
                                                                          return GENICAM_NAMESPACE::gcstring("IBoolean");
                                                                      case intfICommand:
                                                                          return GENICAM_NAMESPACE::gcstring("ICommand");
                                                                      case intfIFloat:
                                                                          return GENICAM_NAMESPACE::gcstring("IFloat");
                                                                      case intfIString:
                                                                          return GENICAM_NAMESPACE::gcstring("IString");
                                                                      case intfIRegister:
                                                                          return GENICAM_NAMESPACE::gcstring("IRegister");
                                                                      case intfICategory:
                                                                          return GENICAM_NAMESPACE::gcstring("ICategory");
                                                                      case intfIEnumeration:
                                                                          return GENICAM_NAMESPACE::gcstring("IEnumeration");
                                                                      case intfIEnumEntry:
                                                                          return GENICAM_NAMESPACE::gcstring("IEnumEntry");
                                                                      case intfIPort:
                                                                          return GENICAM_NAMESPACE::gcstring("IPort");
                                                              // Do not use this pragma in public header files (warnings in depend projects): #pragma BullseyeCoverage off
                                                                      case intfIBase:
                                                                      default:
                                                                          return GENICAM_NAMESPACE::gcstring("IBase");
                                                              // Do not use this pragma in public header files (warnings in depend projects): #pragma BullseyeCoverage on
                                                                      }
                                                                  }
                                                              
                                                                  //! Checks if a node is readable
                                                                  template <class T, class B>
                                                                  inline bool IsReadable( const CPointer<T, B>& ptr)
                                                                  {
                                                                      return ptr.IsValid() && IsReadable( ptr->GetAccessMode() );
                                                                  }
                                                              
                                                                  //! Checks if a node is Writable
                                                                  template <class T, class B>
                                                                  inline bool IsWritable( const CPointer<T, B>& ptr)
                                                                  {
                                                                      return ptr.IsValid() && IsWritable( ptr->GetAccessMode() );
                                                                  }
                                                              
                                                                  //! Checks if a node is Implemented
                                                                  template <class T, class B>
                                                                  inline bool IsImplemented( const CPointer<T, B>& ptr)
                                                                  {
                                                                      return ptr.IsValid() && IsImplemented( ptr->GetAccessMode() );
                                                                  }
                                                              
                                                                  //! Checks if a node is Available
                                                                  template <class T, class B>
                                                                  inline bool IsAvailable( const CPointer<T, B>& ptr)
                                                                  {
                                                                      return ptr.IsValid() && IsAvailable( ptr->GetAccessMode() );
                                                                  }
                                                              
                                                              
                                                                  //! \}
                                                              
                                                              
                                                              }
                                                              
                                                              #endif // ifndef GENAPI_POINTER_H

                                                              Il y a des imports/ exports dans certains fichiers telle que GenApiDll.h

                                                              #if defined(_MSC_VER)
                                                              #   pragma once
                                                              #   define GENAPI_DECL_ABSTRACT /*nothing*/
                                                              #   ifdef GENAPI_EXPORTS
                                                              #       define GENAPI_DECL __declspec(dllexport)
                                                              #   else
                                                              #       define GENAPI_DECL __declspec(dllimport)
                                                              #       define GENAPI_EXPIMP_TEMPL extern
                                                              #   endif
                                                              #elif defined (__GNUC__) && (defined (__linux__) || defined(__APPLE__) || defined(VXWORKS))
                                                              #   define GENAPI_DECL __attribute__((visibility("default"))) 
                                                              #   define GENAPI_DECL_ABSTRACT __attribute__((visibility("default"))) 
                                                              #   ifdef GENAPI_EXPORTS
                                                                      // nothing
                                                              #   else
                                                              #       define GENAPI_EXPIMP_TEMPL extern
                                                              #   endif
                                                              #else
                                                              #   #error Define how to export symbols on your platform!
                                                              #   define GENAPI_DECL
                                                              #   ifndef GENAPI_EXPORTS
                                                              #       define GENAPI_EXPIMP_TEMPL extern
                                                              #   endif
                                                              #endif
                                                              

                                                              gcstring = std::string




                                                              -
                                                              Edité par VincentL10 23 juin 2021 à 13:02:36

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Problème de DLL

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown