Passing a reference of an handle in C++/CLI - reference

I want to delete a 2 level derived class with a function and putting its handle to null.
A piece of code will be helpfull:
ref class bob
{
};
ref class bill : public bob
{
};
ref class jack : public bill
{
};
void DeleteX( bob ^% x )
{
if( x != nullptr )
{
delete x;
x = nullptr;
}
}
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
bill^ one = gcnew jack();
DeleteX(one);
System::Diagnostics::Trace::Assert(one == nullptr); //Failed
return 0;
}
If I use the same type for my declaration and for my function argument, it works.
But I want to use the middle type for my declaration and the upper type for the function argument.
How can I do this please ?
This is the solution I finally use:
template<class T>
void DeleteX( T ^% x )
{
if( x != nullptr )
{
delete x;
x = nullptr;
}
}

It just works for me...
ref class bob
{
};
ref class bill : public bob
{
};
void DeleteX( bob ^% x )
{
if( x != nullptr )
{
delete x;
x = nullptr;
}
}
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
bob^ one = gcnew bill();
DeleteX(one);
System::Diagnostics::Trace::Assert(one == nullptr); //did not trigger

Related

All my sprites are stuck in the upper left corner?

When I call sprite.getPosition() on my sprites I can clearly see that each of them has a different position, but when I draw my sprites every single one of them renders on top of each other?
Here is the full source code thus far:
(I was planning to just pick out the relevant bits, but after 5 minutes of trimming I realized I'd be including 95% of it anyway, so it ends up shorter if I just don't trim it at all)
#include <array>
#include <cassert>
#include <iostream>
#include <vector>
#include <SFML/Graphics.hpp>
sf::Texture spritesheet{};
namespace TextureRects {
std::array<std::array<sf::IntRect,2>, 3> aliens{{
{sf::IntRect{0,0,12,8}, sf::IntRect{36,0,12,8}},
{sf::IntRect{12,0,12,8}, sf::IntRect{48,0,12,8}},
{sf::IntRect{24,0,12,8}, sf::IntRect{60,0,12,8}}
}};
}
class Alien {
public:
enum class Type {
one,
two,
three,
max
};
private:
enum class AnimationState {
in,
out
};
sf::Vector2f m_position{};
Type m_type{};
sf::Sprite m_sprite{};
bool m_alive{ true };
sf::IntRect getTextureRect(AnimationState animationState) const {
return TextureRects::aliens[static_cast<std::size_t>(m_type)][static_cast<std::size_t>(animationState)];
}
void swapTexture() {
static AnimationState s_animationState{ AnimationState::in };
m_sprite.setTextureRect(getTextureRect(s_animationState));
s_animationState = static_cast<AnimationState>(!static_cast<bool>(s_animationState));// in -> out, out -> in
}
void initializeTexture() {
m_sprite.setTexture(spritesheet);
swapTexture();
}
public:
Alien() = default;
Alien(Type type) : m_type{ type } {
initializeTexture();
}
void setPosition(sf::Vector2f position) {
m_sprite.setPosition(position);
m_position = position;
std::cout << m_sprite.getPosition().x << "\n";
std::cout << m_sprite.getPosition().y << "\n";
}
void draw(sf::RenderWindow& window) const{
if (m_alive) {
window.draw(m_sprite);
}
}
void reset() {
m_alive = true;
}
};
class Swarm {
std::vector<Alien> m_aliens{};
void init() {
m_aliens.resize(55);
for (int y{ 0 }; y < 5; ++y) {
for (int x{ 0 }; x < 11; ++x) {
if (y == 0) {
m_aliens.push_back(Alien{ Alien::Type::three });
} else if (y < 3) {
m_aliens.push_back(Alien{ Alien::Type::two });
}else {
m_aliens.push_back(Alien{ Alien::Type::one });
}
}
}
reset();
}
public:
Swarm() {
init();
};
void reset() {
for (std::size_t y{ 0 }; y < 5;++y) {
for (std::size_t x{ 0 }; x < 11;++x) {
auto& alien{ m_aliens[y * 11 + x] };
alien.setPosition({ x * 20.0f, y * 20.0f });
alien.reset();
}
}
}
void draw(sf::RenderWindow& window) const{
for (const auto& alien : m_aliens) {
alien.draw(window);
}
}
};
int main() {
spritesheet.loadFromFile("spritesheet.png");
sf::RenderWindow window{sf::VideoMode{448, 512}, "Space Invaders"};// 224x256 * 2x2.5
sf::View view1{ sf::FloatRect{0,0,224,256} };
window.setView(view1);
Swarm swarm{};
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
}
}
window.clear();
swarm.draw(window);
window.display();
}
return 0;
}
Notice that the std::cout << m_sprite.getPosition().x << "\n"; and std::cout << m_sprite.getPosition().y << "\n"; lines print out unique positions for each sprite, yet the output shows every sprite crammed into the upper left corner...
(I know the spritesheet won't load, hopefully it doesn't need to in order for the stack of white squares to be obvious.)
Here's a screenshot of the output in case it saves someone some time:

pthread_create does not work when a pointer to an object is given as an argument

I don't understand why CLion IDE underlines "pthread_create" and "pthread_join" in red and says "No matching function for call to...". I used a similar code without using the pointer to an object passed to the thread as an argument and it worked.
#include <iostream>
#include <pthread.h>
#define NUM_THREADS 4
using namespace std;
class Animal {
private:
float x, y;
public:
Animal(float x, float y) {
this->x = x;
this->y = y;
}
void print() {
cout<< x << "," << y << endl;
}
};
void *function(Animal *p) {
Animal animal = *p;
animal.print();
}
int main() {
pthread_t thread[NUM_THREADS];
Animal dog[] = {Animal(2, 3), Animal(-1, 2), Animal(5, 2), Animal(5, 10)};
for(int i = 0; i<NUM_THREADS; i++) {
pthread_create(&thread[i], NULL, function, &dog[i]);
}
for(int i = 0; i<NUM_THREADS; i++) {
pthread_join(thread[i]);
}
return 0;
}
I changed the argument of the childThread function from Animal to void *
void *childThread(void *p) {
Animal *animal = (Animal *)p;
animal->print();
}
And added a second argument NULL to pthread_join
pthread_join(thread, NULL)
and now it works

Constructing a child object from parent object in C++

I am trying to construct a child class object from a base class object. I have tried the below code.
class A
{
public:
A();
A(A&& objectName) = default;
virtual void setint(int i);
virtual void getint();
int var;
};
class B: public A
{
public:
virtual void getint();
B(A&& objectName);
int j= 20;
};
A::A()
{
}
void A::setint(int i)
{
var = i;
}
void A::getint()
{
qDebug()<<"From A Var"<<var;
}
void B::getint()
{
qDebug()<<"From B j"<<j;
qDebug()<<"From B Var"<<var;
}
B::B(A&& objectName): A(std::move(objectName))
{
}
And in my Main.cpp I am doing this
#include <memory>
int main(int argc, char *argv[])
{
A *obj = new A();
obj->setint(10);
obj->getint();
A *obj1 = new B(std::move(*obj));
obj->getint();
obj1->getint();
return 0;
}
The result I get is
From A Var 10
From A Var 10
From B j 20
From B Var 10
My question is why am I getting the value of Var after A *obj1 = new B(std::move(*obj)); this line. I thought the object pointed by obj must have been destructed.
Let me copy paste from this answer: https://stackoverflow.com/a/15663912/512225
std::move doesn't move from the object. It just returns an rvalue reference whose referand is the object, making it possible to move from the object.
Anyway your code is terrible. I hope you know. If you don't, ask for a review.

Convert list to a node pointer

I am trying to write a function to search a linked list for an element, but when I try compiling it I get an error saying cannot convert list to node* in assignment. Why is that happening? Isn't my list a node* already?
Code:
#include <iostream>
#include <stdio.h>
using namespace std;
struct node {
int data;
node * next;
};
class list {
public:
list();
void createnode(int value);
int size();
void insert_position(int pos, int value);
void delete_first();
void delete_last();
void remove(int pos);
int get(int pos);
int search(int searchNum);
node * head, * tail;
};
list::list() {
head = NULL;
tail = NULL;
}
node * search(list l, int value) {
node * p;
for (p = l; p != nullptr; p = p - > next) {
if (p - > data == value) return p;
}
return nullptr;
}
No your list is not a node*. list is just a class.
What you are doing is assigning a class object to node*.
node * search(node* l, int value) {
node * p;
for (p = l; p != NULL; p = p -> next) {
if (p -> data == value) return p;
}
return NULL;
}

Using callback function in a directshow filter cause memory leaks

I am using third party API which I get streams from a callback function
int OnNewImage(BYTE *pData, int nLen)
When I run a simple C++ sample program from console
int continue = 1;
int OnNewImage(BYTE *pData, int nLen)
{
std::cout << "On new image is called" << std::endl;
return continue;
}
int main()
{
// This will block
int result = DownloadStream(/*params*/...,OnNewImage /*callbackfunction*/);
return 0;
}
I get no memory leaks.[ memory does not increase ]
But When I use this callback function in a directshow filter, it
produce memory leaks.[ memory increase regularly]
What may cause this? And how can I fix it? Any ideas?
UPDATE: My DirectShow Filter structure
What I do:
Basically
I get streams at "unsigned __stdcall DVRStreamThread(LPVOID
pvParam)" function which call back OnNewImage
Then i insert frames into my queue inside that callback[OnNewImage]
Finally At FillBuffer I consume frames from queue.
It is am h264 stream. I can able to set simple graph like this
MySourceFilter ---> H264 Decoder ---> Video Renderer
Here is my FilterSourceCode:
Well I have a simple queue which i insert incoming frames then consume:
SynchronisedQueue
template <typename T>
class SynchronisedQueue
{
public:
void Enqueue(const T& data)
{
boost::unique_lock<boost::mutex> lock(queueMutex);
dataQueue.push(data);
conditionVariable.notify_one();
}
T Dequeue()
{
boost::unique_lock<boost::mutex> lock(queueMutex);
while (dataQueue.size()==0)
{
conditionVariable.wait(lock);
}
T result=dataQueue.front(); dataQueue.pop();
return result;
}
int Size()
{
boost::unique_lock<boost::mutex> lock(queueMutex);
int size = dataQueue.size();
return size;
}
private:
std::queue<T> dataQueue;
boost::mutex queueMutex;
boost::condition_variable conditionVariable;
};
Then My Filter:
DvrSourceFilter [ header]
#define DVRSourceFilterName L"DVRDirectShowFilter"
#include <streams.h>
#include <process.h>
#include <MyDvrApi.h>
#include "SynchronisedQueue.h"
// {F89A85DA-F77C-4d44-893B-CCA43A49E7EF}
DEFINE_GUID(CLSID_DVRSourceFilter,
0xf89a85da, 0xf77c, 0x4d44, 0x89, 0x3b, 0xcc, 0xa4, 0x3a, 0x49, 0xe7, 0xef);
class DECLSPEC_UUID("34363248-0000-0010-8000-00AA00389B71") Subtype_H264;
class DVRSourceFilter;
using namespace std;
/*
* **********************
* DVRPin
* **********************
*/
class DVRPin : public CSourceStream
{
public:
DVRPin(HRESULT *phr, DVRSourceFilter *pFilter);
~DVRPin();
// Override the version that offers exactly one media type
HRESULT GetMediaType(CMediaType *pMediaType);
HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
HRESULT FillBuffer(IMediaSample *pSample);
static int OnNewImage(void *pUser, BYTE *pData, int nLen, int nCh, int tMts, int nType, void *returnHandle);
// Setters
void SetDvrIp(char* dvrIp);
void SetDvrPort( int dvrPort);
void SetDvrUserName( char * userName);
void SetDvrPassword(char* password);
void SetStartTime(int startTime);
void SetMilliSecond(int milliSecond);
void SetChannelNumber(int channelNumber);
void SetSize(int width, int height);
// Getters
char* GetDvrIp();
int GetDvrPort();
char* GetDvrUserName();
char* GetDvrPassword();
int GetStartTime();
int GetMilliSecond();
int GetChannelNumber();
int GetMode();
public:
char* dvrIp;
int dvrPort;
char* userName;
char* password;
int startTime;
int milliSecond;
int channelNumber;
BITMAPINFOHEADER m_bmpInfo;
BYTE* m_RGB24Buffer;
DWORD m_RGB24BufferSize;
bool streamCompleted;
int hDecHandle;
HANDLE m_hDVRStreamThreadHandle;
unsigned int m_dwThreadID;
SynchronisedQueue<std::vector<BYTE>> IncomingFramesQueue;
protected:
virtual HRESULT OnThreadCreate();
virtual HRESULT OnThreadDestroy();
virtual HRESULT DoBufferProcessingLoop();
};
/*
* **********************
* DVRSourceFilter
* *********************
*
*/
class DVRSourceFilter : public CSource
{
public:
DECLARE_IUNKNOWN;
static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
void SetDVRLiveParameters(char* dvrIP, int dvrPort, char* userName, char* password, int channelNumber, int width, int height);
private:
DVRSourceFilter(IUnknown *pUnk, HRESULT *phr);
~DVRSourceFilter();
private:
DVRPin *m_pPin;
};
DvrSourceFilter [implementation]
#include "DvrSourceFilter.h"
unsigned __stdcall DVRStreamThread(LPVOID pvParam)
{
DVRPin* streamReader = (DVRPin*)pvParam;
int channelBits = 1 << (streamReader->channelNumber - 1);
streamReader->m_RGB24BufferSize = streamReader->m_bmpInfo.biWidth * streamReader->m_bmpInfo.biHeight * 3;
streamReader->m_RGB24Buffer = (BYTE*)malloc(streamReader->m_RGB24BufferSize);
DownloadStream((LPCTSTR)streamReader->dvrIp,
streamReader->dvrPort , (LPCTSTR)streamReader->userName ,
(LPCTSTR)streamReader->password , channelBits, channelBits,
streamReader->startTime, streamReader->milliSecond,
streamReader->OnNewImage, (void*)streamReader);
streamReader->startTime = -2; // End Of Stream
return 0;
}
/*
* ******************
* DVRPin Class
* ******************
*/
DVRPin::DVRPin(HRESULT *phr, DVRSourceFilter *pFilter)
: CSourceStream(NAME("DVR Source Bitmap"), phr, pFilter, L"Out")
{
m_bmpInfo.biSize = sizeof(BITMAPINFOHEADER);
m_bmpInfo.biCompression = BI_RGB;
m_bmpInfo.biBitCount = 24;
m_bmpInfo.biPlanes = 1;
m_bmpInfo.biClrImportant = 0;
m_bmpInfo.biClrUsed = 0;
m_bmpInfo.biXPelsPerMeter = 0;
m_bmpInfo.biYPelsPerMeter = 0;
hDecHandle = 0;
m_RGB24Buffer = NULL;
m_RGB24BufferSize = 0;
streamCompleted = false;
startTime = -1; // Live Stream
*phr = S_OK;
}
DVRPin::~DVRPin()
{
}
int DVRPin::OnNewImage(void *pUser, BYTE *pData, int nLen, int nCh, int tMts, int nType, void *returnHandle)
{
DVRPin* reader = (DVRPin*)pUser;
if(reader->streamCompleted)
{
return false;
}
if(pData)
{
std::vector<BYTE> vecFrame(pData, pData + nLen/sizeof(pData[0]));
reader->IncomingFramesQueue.Enqueue(vecFrame);
}
return !reader->streamCompleted;
}
HRESULT DVRPin::OnThreadCreate()
{
m_hDVRStreamThreadHandle =
(HANDLE)_beginthreadex(NULL, 0, &DVRStreamThread, (void*)this, 0, &m_dwThreadID);
return S_OK;
}
HRESULT DVRPin::OnThreadDestroy() {
streamCompleted = true;
_endthreadex(0);
CloseHandle(m_hDVRStreamThreadHandle);
return S_OK;
}
HRESULT DVRPin::GetMediaType(CMediaType *pMediaType)
{
CAutoLock cAutoLock(m_pFilter->pStateLock());
CheckPointer(pMediaType, E_POINTER);
VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
if (pvi == 0)
return(E_OUTOFMEMORY);
ZeroMemory(pvi, pMediaType->cbFormat);
pvi->bmiHeader = m_bmpInfo;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
SetRectEmpty(&(pvi->rcSource));
SetRectEmpty(&(pvi->rcTarget));
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);
// Work out the GUID for the subtype from the header info.
const GUID SubTypeGUID = __uuidof(Subtype_H264);//GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);
return S_OK;
}
HRESULT DVRPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest)
{
HRESULT hr;
CAutoLock cAutoLock(m_pFilter->pStateLock());
CheckPointer(pAlloc, E_POINTER);
CheckPointer(pRequest, E_POINTER);
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*) m_mt.Format();
if (pRequest->cBuffers == 0)
{
pRequest->cBuffers = 2;
}
pRequest->cbBuffer = pvi->bmiHeader.biSizeImage;
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pRequest, &Actual);
if (FAILED(hr))
{
return hr;
}
if (Actual.cbBuffer < pRequest->cbBuffer)
{
return E_FAIL;
}
return S_OK;
}
HRESULT DVRPin::FillBuffer(IMediaSample *pSample)
{
if(!streamCompleted)
{
CAutoLock cAutoLock(m_pLock);
HRESULT hr;
BYTE* pData = NULL;
hr = pSample->GetPointer(&pData);
if(FAILED(hr))
{
pSample->Release();
return hr;
}
if(IncomingFramesQueue.Size() <= 0) {
return S_OK;
}
vector<BYTE> data = IncomingFramesQueue.Dequeue();
int dataSize = (int)data.size();
if(dataSize <= 0 || dataSize > 1000000)
{
return S_OK;
}
memcpy(pData, &data[0], dataSize);
hr = pSample->SetActualDataLength(dataSize);
if(FAILED(hr))
{
pSample->Release();
return hr;
}
hr = pSample->SetSyncPoint(TRUE);
if(FAILED(hr))
{
pSample->Release();
return hr;
}
pSample->Release();
}
return S_OK;
}
HRESULT DVRPin::DoBufferProcessingLoop() {
Command com;
REFERENCE_TIME rtNow = 0L;
REFERENCE_TIME rtAdvise = 0L;
OnThreadStartPlay();
do {
while (!streamCompleted && !CheckRequest(&com)) {
IncomingFramesQueue.WaitUntilHaveElements();
IMediaSample *pSample;
HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,FALSE);
if (FAILED(hr)) {
continue; // go round again. Perhaps the error will go away
// or the allocator is decommited & we will be asked to
// exit soon.
}
hr = FillBuffer(pSample);
if (hr == S_OK) {
Deliver(pSample);
} else if (hr == S_FALSE) {
pSample->Release();
DeliverEndOfStream();
return S_FALSE;
} else {
// Log Error
}
pSample->Release();
}
if (com == CMD_RUN || com == CMD_PAUSE)
com = GetRequest(); // throw command away
else if (com != CMD_STOP)
{
// Log Error
}
} while (!streamCompleted && com != CMD_STOP);
return S_OK;
}
void DVRPin::SetDvrIp( char* dvrIp )
{
this->dvrIp = dvrIp;
}
void DVRPin::SetDvrPort( int dvrPort )
{
this->dvrPort = dvrPort;
}
void DVRPin::SetDvrUserName( char * userName )
{
this->userName = userName;
}
void DVRPin::SetDvrPassword( char* password )
{
this->password = password;
}
void DVRPin::SetStartTime( int startTime )
{
this->startTime = startTime;
}
void DVRPin::SetMilliSecond( int milliSecond )
{
this->milliSecond = milliSecond;
}
void DVRPin::SetSize(int width, int height) {
m_bmpInfo.biWidth = width;
m_bmpInfo.biHeight = height;
m_bmpInfo.biSizeImage = GetBitmapSize(&m_bmpInfo);
}
char* DVRPin::GetDvrIp()
{
return dvrIp;
}
int DVRPin::GetDvrPort()
{
return dvrPort;
}
char* DVRPin::GetDvrUserName()
{
return userName;
}
char* DVRPin::GetDvrPassword()
{
return password;
}
int DVRPin::GetStartTime()
{
return startTime;
}
int DVRPin::GetMilliSecond()
{
return milliSecond;
}
void DVRPin::SetChannelNumber( int channelNumber )
{
this->channelNumber = channelNumber;
}
int DVRPin::GetChannelNumber()
{
return channelNumber;
}
/*
* ****************************
* DVRSourceFilter Class
* ***************************
*/
DVRSourceFilter::DVRSourceFilter(IUnknown *pUnk, HRESULT *phr)
: CSource(NAME("DVRSourceBitmap"), pUnk, CLSID_DVRSourceFilter)
{
// The pin magically adds itself to our pin array.
m_pPin = new DVRPin(phr, this);
// Just for test at graph studio
SetDVRLiveParameters("192.168.3.151", 7000, "admin", "000000", 3, 352, 288);
if (phr)
{
if (m_pPin == NULL)
*phr = E_OUTOFMEMORY;
else
*phr = S_OK;
}
}
DVRSourceFilter::~DVRSourceFilter()
{
delete m_pPin;
}
CUnknown * WINAPI DVRSourceFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr)
{
DVRSourceFilter *pNewFilter = new DVRSourceFilter(pUnk, phr);
if (phr)
{
if (pNewFilter == NULL)
*phr = E_OUTOFMEMORY;
else
*phr = S_OK;
}
return pNewFilter;
}
STDMETHODIMP DVRSourceFilter::NonDelegatingQueryInterface( REFIID riid, void **ppv )
{
return CSource::NonDelegatingQueryInterface(riid, ppv);
}
void DVRSourceFilter::SetDVRLiveParameters( char* dvrIP, int dvrPort, char* userName, char* password, int channelNumber, int width, int height )
{
m_pPin->SetDvrIp(dvrIP);
m_pPin->SetDvrPort(dvrPort);
m_pPin->SetDvrUserName(userName);
m_pPin->SetDvrPassword(password);
m_pPin->SetChannelNumber(channelNumber);
m_pPin->SetStartTime(-1);// Live Stream
m_pPin->SetMilliSecond(0);
m_pPin->SetSize(width, height);
}
...
To make directshow Filter simple [ to understand memory leak source], just implement OnNewImage function and FillBufferFunction as "dummy", but still has memory leak:
int DVRPin::OnNewImage(void *pUser, BYTE *pData, int nLen, int nCh, int tMts, int nType, void *returnHandle)
{
return 1; // for not to end call back
}
HRESULT DVRPin::FillBuffer(IMediaSample *pSample)
{
pSample->Release();
return S_OK;
}
In DVRStreamThread, you have:
streamReader->m_RGB24Buffer = (BYTE*)malloc(streamReader->m_RGB24BufferSize);
But I don't see a matching call to free() anywhere. When your DVRPin object is deleted, you will have to explicitly free the data pointed to by its m_RGB24Buffer member.
First thing I see, is that your destructors are not virtual. This might be a cause of leaks when release is not taking place when inheritance is used. See related article about the necessity of virtual destructors.

Resources