Access Violation : Tentative de lecture ou écriture de mémoire partagée
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:
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 :
Code:
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;
} ; |
Le but est de faire tourner la caméra en créant le "nécessaire" (comme une brute dans l'appli principale)
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
Code:
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 ;
}
} |
Mais lorsque j'arrive à la ligne en gras , ça se corse :
Code:
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();
....
} |
Plus précisément planté au code ligne suivante (source du fournisseur de Caméra)
Code:
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)");
} |
Première chose : je ne suis pas doué pour m'exprimer...
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...