Click here to Skip to main content
15,891,473 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi guys! After 13 years of losing my real programming skills by getting sucked into Java I've decided to dive back into C++. I wrote a small program to read from a webcam and display the output and now I'm going back and trying to make a framework out of this application. I have one method that just is not working how I would expect and I'm sure the experts here can help.

Here is what I have. This method interrogates the device driver to extract information about a device and builds an object that stores this information then places that object in a vector. This seems to work fine.

HRESULT WebCamDeviceList::RegisterDevice(UINT32 index, IMFActivate* vDevice,  IMFMediaSource* vMediaSource, IMFSourceReader* vMediaReader) {
	HRESULT hr = S_OK;
	LPWSTR dFriendlyName = NULL;
	UINT32 dName = NULL;
         //dFriendlyName returns allocated memory and will need to be cleaned up as some
         //point
	hr = vDevice[index].GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &dFriendlyName, &dName);

	if(SUCCEEDED(hr)) {
		WebCamDevice* wDevice = new WebCamDevice();

		wDevice->SetIndex(index);
		wDevice->SetName(dName);
		wDevice->SetFriendlyName(dFriendlyName);

		wDevice->LoadConfiguration(vMediaSource, vMediaReader);

		_DeviceList.push_back(wDevice);

	} else {
		MessageBox(NULL,TEXT("Unable to retieve device name"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
	}


	return hr;
}


This piece of code retrieves that object pointer from the vector and passes it back to the caller. Using the debugger the retrieval of the object pointer seems to work fine. The problem is that the "device" parameter is passed back with no values almost like it went out of scope and if it was Java I would assume the GCer got it.


HRESULT WebCamDeviceList::GetDevice(size_t index, WebCamDevice** device) {
	HRESULT hr = S_OK;
	WebCamDevice* cDevice = NULL;
	if (index < _DeviceList.size()) {
	  cDevice = _DeviceList[index];
	}
	device = &cDevice;
	return hr;
}



If this helps here is the caller. The line "deviceList->GetDevice(index, &device)" passes back a empty object even though right before it exits I can see the pointer is valid with the debugger.

WebCamDeviceList* deviceList = new WebCamDeviceList();
deviceList->LoadDevices();
deviceList->GetCount(&numberDevices);

size_t index = 0;

mainWindow = new GuiMain(hWnd,hInstance);
while( index < numberDevices ) {
    //MessageBox(NULL,TEXT("Device One" ), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
     WebCamDevice* device = NULL;
     deviceList->GetDevice(index, &device);
    //((WebCamVideoConfig*)(device->VideoConfig)->WebCamVideoConfig::SetWidth(width);
     if(device->GetFriendlyName() != NULL) {
         SendMessage(mainWindow->DeviceListBox, LB_ADDSTRING, 0, (LPARAM)device->GetFriendlyName());
     }
    index++;
}


This has to be something very simple and I feel like a fool not understanding what is going on since I used to do this for a living but Java has destroyed my pointer and memory management skills.

Thank you in advance for any help.
Kevin
Posted
Updated 28-Sep-13 8:34am
v3
Comments
lrinish 28-Sep-13 22:48pm    
I guess I should have tried this before I responded. It just made sense so I thought it would solve the issue but device is still NULL after the caller returns. Like mentioned I have no trouble returning "WebCamDevice*" but when I pass it back it gets lost. I tried two more methods passing by pointer (no pointer to pointer) and by reference. Passing by pointer ends with a NULL value and passing by reference returns with an uninitialized object. Its almost acting like its passing the parameter by value.

1 solution

Quote:
Ok so pasztorpisti's original solution was correct. The problem was that I tried to listen to "Kenneth's" suggestion and eliminate the pointer to pointer solution but found out that is actually the proper solution in this case. When passing just WebCamDevice* the pointer itself was being passed by value so I couldn't reassign it which was the entire goal. The entire problem was like pasztorpisti's example I should have been de-referencing the pointer and assigning the pointer stored in the vector. So yes there are cases where a pointer to a pointer is required. Matter of fact many of the Window's APIs I'm using do that exact same thing such as "ActivateObject" and "MFCreateSourceReaderFromMediaSource". Passing a reference to the pointer might have worked but the pointer needs to be initialized to NULL else you receive a warning. Once again thank you pasztorpisti your analysis of my stupid mistake was correct. The only thing is I don't want to propagate that the ** or *& solution is not correct because in this case its is the correct one. Any other solution wouldn't have met my requirement or required me to create and manage a needless struct or another class.

The final solution looks like this.

C#
WebCamDevice* tDevice = NULL;
 deviceList->GetDevice(index, &tDevice);
//((WebCamVideoConfig*)(device->VideoConfig)->WebCamVideoConfig::SetWidth(width);

 if(tDevice->GetFriendlyName() != NULL) {
     SendMessage(mainWindow->DeviceListBox, LB_ADDSTRING, 0, (LPARAM)tDevice->GetFriendlyName());
 }

HRESULT WebCamDeviceList::GetDevice(size_t index, WebCamDevice** lDevice) {
	HRESULT hr = S_OK;
	WebCamDevice* cDevice = NULL;
	if (index < _DeviceList.size()) {
	  *lDevice = _DeviceList[index];
	}
	return hr;
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900