Bonjour à tous,
Je sollicite votre aide à propos d'une intégration hardware qui me pose réellement des soucis. Je m'explique :
Dans le cadre d'une application je dois intégrer une nouvelle caméra dans un environnement C++/CLI et c'est là que je pêche... (Je suis plus habitué au code natif et autres MFC).
Bien entendu, les sources/DLL de la caméra est en natif et je tiens à vous dire que le code sur lequel je travaille n'est pas de moi : il est réellement rude et barbare (static dans tous les sens...) pour mon oeil non averti...
J'ai une DLL managée (et un namespace) qui regroupe les fonctions initialisation, snap de la cam... : (au passage je tiens à signaler que les sources de cette DLL tournent sans problème avec une appli native)
DLL :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 static void CameraBasler::InitColorCam(CameraColor* Cam,size_t &BufferSize,CLogBasler ^pLog); static voidCameraBasler::InitBufferCam(CameraColor* Cam,CLogBasler ^pLog); static bool CameraBasler::Snap(CameraColor* Cam,System::Drawing::Bitmap^% bmp,CLogBasler ^pLog); }
Lorsque je lance ces deux fonctions successivement je plante en access violation avec Tentative de lecture ou écriture de mémoire partagée.
J'ai une structure CameraColor qui ressemble à ceci :
Le but est de faire tourner la caméra en créant le "nécessaire" (comme une brute dans l'appli principale)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 struct CameraColor { Pylon::CBaslerGigECamera m_CamColor; Pylon::CBaslerGigECamera::StreamGrabber_t m_StreamGrabber; static const size_t m_ImageSize=5045424; uint8_t m_Buffer[m_ImageSize]; StreamBufferHandle m_hBuffer; } ;
Je sais c'est très moche! (A ma décharge, j'ai repris cette architecture bouchère de la part du précédent développeur et en passant par des objets de classe l'erreur persistait...)
Du Coup, dans le Load de ma Form, je passe sans encombre la première fonction
Mais lorsque j'arrive à la ligne en gras , ça se corse :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 public ref class CameraBasler { void CameraBasler::InitColorCam(CameraColor* Cam,size_t &BufferSize,CLogBasler ^pLog) { try { Pylon::PylonAutoInitTerm autoInitTerm; // Get the transport layer factory CTlFactory& TlFactory = CTlFactory::GetInstance(); // Create the transport layer object needed to enumerate or // create a camera object of type Camera_t::DeviceClass() ITransportLayer *pTl = TlFactory.CreateTl(Pylon::CBaslerGigECamera::DeviceClass()); // Exit the application if the specific transport layer is not available if (! pTl) { pLog->AddString("Error : Failed to create transport layer!",true); return; } // Get all attached cameras and exit the application if no camera is found DeviceInfoList_t devices; if (0 == pTl->EnumerateDevices(devices)) { pLog->AddString("Error : No Basler Camera Present!",true); return ; } // Create the camera object of the first available camera. // The camera object is used to set and get all available // camera features. Cam->m_CamColor.Attach(pTl->CreateDevice(devices[0])); bool bTest = false; if(Cam->m_CamColor.IsAttached()) { // Open the camera Cam->m_CamColor.Open(); if(Cam->m_CamColor.IsOpen())bTest = true; } // Get the first stream grabber object of the selected camera Cam->m_StreamGrabber.Attach(Cam->m_CamColor.GetStreamGrabber(0)); bTest = Cam->m_StreamGrabber.IsAttached(); // Open the stream grabber Cam->m_StreamGrabber.Open(); bTest = Cam->m_StreamGrabber.IsOpen(); // Set the image format and AOI Cam->m_CamColor.PixelFormat.SetValue(PixelFormat_BayerBG8); Cam->m_CamColor.OffsetX.SetValue(0); Cam->m_CamColor.OffsetY.SetValue(0); Cam->m_CamColor.Width.SetValue(Cam->m_CamColor.Width.GetMax()); Cam->m_CamColor.Height.SetValue(Cam->m_CamColor.Height.GetMax()); //Disable acquisition start trigger if available { GenApi::IEnumEntry* acquisitionStart = Cam->m_CamColor.TriggerSelector.GetEntry( TriggerSelector_AcquisitionStart); if ( acquisitionStart && GenApi::IsAvailable( acquisitionStart)) { Cam->m_CamColor.TriggerSelector.SetValue( TriggerSelector_AcquisitionStart); Cam->m_CamColor.TriggerMode.SetValue( TriggerMode_Off); } } //Disable frame start trigger if available { GenApi::IEnumEntry* frameStart =Cam->m_CamColor.TriggerSelector.GetEntry( TriggerSelector_FrameStart); if ( frameStart && GenApi::IsAvailable( frameStart)) { Cam->m_CamColor.TriggerSelector.SetValue( TriggerSelector_FrameStart); Cam->m_CamColor.TriggerMode.SetValue( TriggerMode_Off); } } //Set acquisition mode Cam->m_CamColor.AcquisitionMode.SetValue(AcquisitionMode_SingleFrame); //Set exposure settings Cam->m_CamColor.ExposureMode.SetValue(ExposureMode_Timed); Cam->m_CamColor.ExposureTimeRaw.SetValue(100); // Create an image buffer BufferSize = (size_t)(Cam->m_CamColor.PayloadSize.GetValue()); } catch (GenICam::GenericException &e) { // Error handling pLog->AddString("Error : An exception occurred!",true); return ; } }
Plus précisément planté au code ligne suivante (source du fournisseur de Caméra)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 void CameraBasler::InitBufferCam(CameraColor* Cam,CLogBasler ^pLog) { int iSize = Cam->m_ImageSize; // We won't use image buffers greater than ImageSize Cam->m_StreamGrabber.MaxBufferSize.SetValue(iSize,false); // We won't queue more than one image buffer at a time Cam->m_StreamGrabber.MaxNumBuffer.SetValue(1); // Allocate all resources for grabbing. Critical parameters like image // size now must not be changed until FinishGrab() is called.*/ Cam->m_StreamGrabber.PrepareGrab(); .... }
Première chose : je ne suis pas doué pour m'exprimer...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 virtual void SetValue(int64_t Value, bool Verify = true) { if(ref::m_Ptr) return ref::m_Ptr->SetValue(Value, Verify); else throw ACCESS_EXCEPTION("Feature not present (reference not valid)"); }
Ensuite, je répète, les mêmes fonctions de la DLL tournent à partir d'une base vierge...
Questions : (en vrac)
Une idée de la provenance de mes soucis ?
Comment peut-on créer un pointeur d'une classe managée que l'on pourrait gérer comme en natif (allocation/désallocation) ?
Meric d'avance, et je vous prie d'être indulgent sur mon niveau, svp...
Partager