ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Auto free SelectionSet's name

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
trithuongle
407 Views, 6 Replies

Auto free SelectionSet's name

Hello everybody. I had a question.

I'm creating a simple class to auto free SelectionSet's name(acedSSFree) when my SSNameRel object goes out of its scope.

My code is below. It seems that the command ran without errors. But I'm not sure what I'm doing is correct? 
Cause at the step「acedSSFree(_ssNameVector[i])」I'm transferring the int64_t* instead of the ads_name.

The reason for this is when I tried to use ads_name, It will generate error at the step Vector::push_back(ads_name ssName) so I decided to use int64_t* instead.
Thanks in advance!

/// <summary>
/// Help class to auto free multiple SelectionSet name
/// when its object goes out of scope.
/// </summary>
class SSNameRel
{
public:
	SSNameRel();
	~SSNameRel();
	void AddAdsName(int64_t* ssName);

private:
	std::vector<int64_t*> _ssNameVector;
};

SSNameRel::SSNameRel()
{

}

void SSNameRel::AddAdsName(int64_t* ssName)
{
	_ssNameVector.push_back(ssName);
}

SSNameRel::~SSNameRel()
{
	size_t vectorSize = _ssNameVector.size();
	if (vectorSize > 0 )
	{
		for (size_t i = 0; i < vectorSize; i++)
		{
			if (acedSSFree(_ssNameVector[i]) != RTNORM)
			{
				acrx_abort(L"\nCannot free selection name!");
			}
		}
	}
}
//Sample to illustrate the implementation of auto SelectionSet's name free:
void TestSS1()
{
	SSNameRel mySSNameRel;

	ads_name ssName;
	int rc;

	int MaxCount = 5; //Ask user select 5 times
	for (int i = 0; i < MaxCount; i++)
	{
		rc = acedSSGet(NULL, NULL, NULL, NULL, ssName);
		if (rc == RTCAN)
		{
			return;
		}
		else if (rc == RTERROR || rc == RTNONE)
		{
			acutPrintf(L"\nCannot get SelectionSet!");
			return;
		}
		else
		{
			acutPrintf(L"\nYour Selection set %d", i + 1);
			mySSNameRel.AddAdsName(ssName);

			Adesk::Int32 ssLen;
			acedSSLength(ssName, &ssLen);

			acutPrintf(L"\nNumber of selected items: %d", ssLen);
		}
	}
}

 

6 REPLIES 6
Message 2 of 7

What about using ArxDbgSelSet class from ObjectARX SDK sample ARXDBG ( samples\database\ARXDBG\AcadUtils\ArxDbgSelSet.cpp ) ? 

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 3 of 7

@Alexander.Rivilis Thanks for your reply.

I saw the code of ArxDbgSelSet 's class. I think this class is very detailed for many cases of SelectionSet.

I will consider to use this when handling with multiple types of selection.

But now I want to know that when using acutSSFree(ads_name), if i pass the first element's address of ads_name array, so the function acutSSFree(int64_t *) will return RTNORM. So I think at this time my SelectionSet is released successfully, but am I wrong?

Thanks in advance!

Message 4 of 7
tbrammer
in reply to: trithuongle

Your code will not work in general. But it can be fixed easily.

void SSNameRel::AddAdsName(int64_t* ssName) {
  _ssNameVector.push_back(ssName);
}
This code stores only the address of the selectionset, not the data. It will work only, if the ads_name of the selectionset and the SSNameRel object have the same scope. So you test code would work:
 
void TestSS1() {
  ads_name ssName;
  SSNameRel mySSNameRel;  // same scope as ssName. OK.
  acedSSGet(NULL, NULL, NULL, NULL, ssName);
  mySSNameRel.AddAdsName(ssName);
}
 
But this would not work:
 
void BadSelection(SSNameRel &mySSNameRel)  {
  ads_name ssName;
  acedSSGet(NULL, NULL, NULL, NULL, ssName);
  mySSNameRel.AddAdsName(ssName);
}

void BadSelSecUsage() {
  SSNameRel mySSNameRel;
  BadSelection(SSNameRel &mySSNameRel);
  use(mySSNameRel); // NO! ads_name is out of scope. 
                    // int64_t* in _ssNameVector points to released memory
  ...
}
 
A safe way to store the selectionset is to put it into a struct or class:
 
class SelSetContainer
{
public:
  SelSetContainer(ads_name ss) {
    ads_name_set(ss, m_ss);
  }
  void free() {
    acedSSFree(m_ss);
  }
private:
  ads_name m_ss;
};

class SSNameRel
{
public:
  ~SSNameRel() {
    for (auto &ss : _ssNameVector)
      ss.free();
  }
  void AddAdsName(ads_name ss) {
    _ssNameVector.push_back(SelSetContainer(ss));
  }
private:
  std::vector<SelSetContainer> _ssNameVector;
};

 


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

Message 5 of 7
trithuongle
in reply to: tbrammer

@tbrammer Thanks for your reply. I understood your solution.

I think your instruction is very clear and understandable. 

More over this also help me to understand more about bad usage when Release Object and ssname not in the same scope.

One more thing I want to ask related to using acedSSGetKwordCallbackPtr(). As I saw in this post,
https://adndevblog.typepad.com/autocad/2013/01/using-acedsssetkwordcallbackptr-on-selections.html
author store the old function pointer first, then set the new one, then set back to the old funtion pointer before going out of the method.

I tried to not store the old function pointer and set the new one directly, the sample command still run well.
After the sample command is finished I tried other Autocad's commands(Move/ copy ...vv) to test whether the KeyWordCallBack still remember the above new function pointer but it seems that when above sample command finished. KeyWordCallBack  is auto set back to the original set up, but I don't know if I made any mistake?
Thanks in advance!

 

Message 6 of 7
tbrammer
in reply to: trithuongle

The ARX docs say that the old function pointer should be restored.

I don't know what happens if you don't do this. Maybe you run into problems if another 3rd party module changed the function pointer. I would just restore it after switching and using my own.


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

Message 7 of 7
trithuongle
in reply to: tbrammer

@tbrammer Thanks for your reply.  I'm so thankful for your help.
Have a nice day!

 

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report