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

AcDbBlockTableRecord::getName(...).. two signatures, different results

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
reganproulx
997 Views, 7 Replies

AcDbBlockTableRecord::getName(...).. two signatures, different results

Using RealDWG 2014, I recently changed some calls like getName(...) for several RealDWG objects to manage strings differently. I moved them from using the ACHAR*& signature, to the AcString& signature. The expectation was that I could avoid having to free the allocated memory buffer explicitly with acutDelString after.

 

However, upon testing, the AcDbBlockTableRecord::getName(AcString&) method call, inherited from AcDbSymbolTableRecord, returned different results than the previous AcDbBlockTableRecord::getName(ACHAR*&) call.

 

In the attached sample, the block name is '*U0'. The ACHAR*& call returned '*U0', but the AcString& call returned this:

 

mwszStr	"*U" wchar_t [3]

 

Why is that? Should they not return the same thing?

 

Thanks,

Regan

 

7 REPLIES 7
Message 2 of 8
owenwengerd
in reply to: reganproulx

How exactly did you determine that the returned names are different? I suspect that you're misinterpreting the AcString return value. You could rule out such misinterpretation by converting the AcString to an ACHAR*, then using lstrcmp() to compare that to the result of the ACHAR*& function.

--
Owen Wengerd
ManuSoft
Message 3 of 8
reganproulx
in reply to: owenwengerd

Owen, my understanding is that the string values may be misunterpreted if I manually typed the intepretation of the AcString guts, but if the returned AcString is asked for the contents, then there is no intepretation except for what the interface to AcString provides, with the types provided by those signatures.

 

The following shows the AcString contents as requested, and that the resutls as different from the basic ACHAR*& call results.

 

ACHAR*& example call and result as seen in debugging

ACHAR* pBuf = NULL;
pBTR->getName(pBuf);
  pBuf 0x0000000008e1dfb0 "*U0" const wchar_t *

 

AcString*& example call and result as seen in debugging

AcString tempName;
pBTR->getName(tempName);
tempName {mnFlags='' mnPad2=0x000000000012bb51 "" mpwszData=0x0000000000000000 <Bad Ptr> ...} AcString
  mwszStr 0x000000000012bb52 "*U" wchar_t [7]

If that AcString result is queried for its contents

const ACHAR* tempBuf = tempName.kACharPtr();
  tempBuf 0x000000000012bb52 "*U" const wchar_t *

const char* tempBufA = tempName.kszPtr();
  tempBufA 0x0000000008e206a8 "*U" const char *

const wchar_t* tempBufW = tempName.kwszPtr();
  tempBufW 0x0000000008e1dff0 "*U" const wchar_t *

 

That seems like enough proof that the strings are different. Comparing NULL terminated strings pBuf and tempBuf, given the above inspection would not return the same string.

 

This still looks like a bug to me, or something to be learned about 'unnamed' block naming.

 

Message 4 of 8
owenwengerd
in reply to: reganproulx

It's always a little risky to rely on what you observe visually in the debug window. Better to actually write the code to compare results at runtime. However, I agree that it does appear to be returning different results. I've never heard of this, but maybe someone from Autodesk can either verify that it is a bug or explain the behavior.

--
Owen Wengerd
ManuSoft
Message 5 of 8

I was able to test it quickly in a sample project I had, I've reproduced the issue displaying annonymous block table record name in the command line:

 

AcString acstr;
ACHAR *lpstr;
pRec->getName(acstr);
pRec->getName(lpstr);
acutPrintf(_T("acstr='%s' (len=%d), lpstr='%s'",static_cast<const TCHAR*>(acstr),acstr.length(),lpstr);

 

actually displays 

 

acstr='*U' (len=2), lpstr='*U10'

 It really looks like a bug.

20-20 CAD / 20-20 Technologies
Message 6 of 8

It is a bug.  The numer in the name of an anonymous block is applied at runtime (it's an index value that can change) by the getName() method.  It is unique to BlockTableRecord names.  The ACHAR* version of the getName() method is overridden in the AcDbBlockTableRecord class to deal with this.  Unfortunately, the AcString version of the getName() method is not overridden in the AcDbBlockTableRecord class, so the AcDbSymbolTableRecord implementation is used and that doesn't know anything about the number part of the name.

 

I'll get this fixed for the next release of Acad/RealDWG.

Message 7 of 8
reganproulx
in reply to: artc2

Cheers.

 

Message 8 of 8
artc2
in reply to: reganproulx

By the way, you can work around this by simply using the const ACHAR* getName method to get the name string and then assign that to your AcString.  The const ACHAR* version of getName just returns a pointer to the internal name string, so there is no memory allocation/deallocation to deal with.  That's how I've implemented the AcDbBlockTableRecord override of the AcString version of getName that I'll be putting into the next release of Acad/RealDWG.  Something like this:

 

    AcString nameStr;

    const ACHAR* tmpName;
    pBlk->getName(tmpName);
    nameStr = tmpName;

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

Post to forums  

Autodesk Design & Make Report

”Boost