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

Trying to understand command macros in arxentrypoint.h

3 REPLIES 3
Reply
Message 1 of 4
Anonymous
553 Views, 3 Replies

Trying to understand command macros in arxentrypoint.h

There are two macros defined in ..\2008\inc\arxentrypoint.h that
automagically registers commands in AcRxArxApp::On_kInitAppMsg.

I've been going through arxentrypoint.h, trying to understand how this code
works but there's one question I can't find and answer to.

I'm hoping that someone here might know the answer.



This is what I DO understand from the code in arxentrypoint.h:

A struct is defined that has all the info needed to register a command:

{code}

struct _ARXCOMMAND_ENTRY {

const ACHAR *pszCmdGroupName ;

const ACHAR *pszCmdGlobalName ;

const ACHAR *pszCmdLocalName ;

Adesk::Int32 commandFlags ;

AcRxFunctionPtr pCmdFct ;

AcEdUIContext *pUIContext ;

UINT localNameID ;

} ;

{code}



Three data sections are defined in the obj file:

{code}

#pragma section("ARXCOMMAND$__a", read, shared)

#pragma section("ARXCOMMAND$__z", read, shared)

#pragma section("ARXCOMMAND$__m", read, shared)

{code}



__pArxCmdMapEntryFirst is allocated to section ARXCOMMAND$__a
and __pArxCmdMapEntryLast is allocated to section ARXCOMMAND$__z:

{code}

extern "C" {

__declspec(selectany) __declspec(allocate("ARXCOMMAND$__a"))
_ARXCOMMAND_ENTRY* __pArxCmdMapEntryFirst =NULL ;

__declspec(selectany) __declspec(allocate("ARXCOMMAND$__z"))
_ARXCOMMAND_ENTRY* __pArxCmdMapEntryLast =NULL ;

}

{code}



Macros that export pointers to _ARXCOMMAND_ENTRY objects are defined:

{code}

#ifdef _WIN64

#define ACED_ARXCOMMAND_ENTRY_PRAGMA(group,globCmd)
__pragma(comment(linker, "/include:__pArxCmdMap_" #group #globCmd)) ;

#else

#define ACED_ARXCOMMAND_ENTRY_PRAGMA(group,globCmd)
__pragma(comment(linker, "/include:___pArxCmdMap_" #group #globCmd)) ;

#endif

{code}



Two macros that create an instance of _ARXCOMMAND_ENTRY, and then allocate a
pointer to the object within the ARXCOMMAND$__m section are defined:

{code}

#define ACED_ARXCOMMAND_ENTRY_AUTO(classname, group, globCmd, locCmd,
cmdFlags, UIContext) \

__declspec(selectany) _ARXCOMMAND_ENTRY __ArxCmdMap_##group##globCmd =
{ _RXST(#group), _RXST(#globCmd), _RXST(#locCmd), cmdFlags,
classname::##group ##globCmd, UIContext, -1 } ; \

extern "C" __declspec(allocate("ARXCOMMAND$__m")) __declspec(selectany)
_ARXCOMMAND_ENTRY* const __pArxCmdMap_##group##globCmd =
&__ArxCmdMap_##group##globCmd ; \

ACED_ARXCOMMAND_ENTRY_PRAGMA(group, globCmd)

#define ACED_ARXCOMMAND_ENTRYBYID_AUTO(classname, group, globCmd, locCmdId,
cmdFlags, UIContext) \

__declspec(selectany) _ARXCOMMAND_ENTRY __ArxCmdMap_##group##globCmd =
{ _RXST(#group), _RXST(#globCmd), NULL, cmdFlags, classname::##group
##globCmd, UIContext, locCmdId } ; \

extern "C" __declspec(allocate("ARXCOMMAND$__m")) __declspec(selectany)
_ARXCOMMAND_ENTRY* const __pArxCmdMap_##group##globCmd =
&__ArxCmdMap_##group##globCmd ; \

ACED_ARXCOMMAND_ENTRY_PRAGMA(group, globCmd)

{code}



When the arx application is loaded, interate through the pointers to
_ARXCOMMAND_ENTRY objects and register each command using
AcEdCommandStack::addCommand:

{code}

virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {

AcRx::AppRetCode retCode =AcRxDbxApp::On_kInitAppMsg (pkt) ;

_ARXCOMMAND_ENTRY **ppArxCmdMapEntryFirst =&__pArxCmdMapEntryFirst + 1 ;

_ARXCOMMAND_ENTRY **ppArxCmdMapEntryLast =&__pArxCmdMapEntryLast ;

ACHAR buffer [133] ;

for ( _ARXCOMMAND_ENTRY **ppEntry =ppArxCmdMapEntryFirst ; ppEntry <
ppArxCmdMapEntryLast ; ppEntry++ ) {

if ( *ppEntry != NULL ) {

if ( (*ppEntry)->pszCmdLocalName == NULL )

::LoadString (m_hdllInstance, (*ppEntry)->localNameID, buffer,
132) ;

acedRegCmds->addCommand (

(*ppEntry)->pszCmdGroupName,

(*ppEntry)->pszCmdGlobalName,

(*ppEntry)->pszCmdLocalName == NULL ? buffer :
(*ppEntry)->pszCmdLocalName,

(*ppEntry)->commandFlags,

(*ppEntry)->pCmdFct,

(*ppEntry)->pUIContext,

-1,

((*ppEntry)->commandFlags & ACRX_CMD_SESSION) ? NULL :
m_hdllInstance,

NULL

) ;

}

}

return (retCode) ;

}

{code}



This all seems very straight forward.

There's just one thing that I don't understand.

How does &__pArxCmdMapEntryFirst + 1 and &__pArxCmdMapEntryLast point to the
first and last _ARXCOMMAND_ENTRY*?

I would think that #pragma section would place sections in an obj file one
after the next in the order they appear,

so if the sections were instead defined as:

{code}

#pragma section("ARXCOMMAND$__a", read, shared)

#pragma section("ARXCOMMAND$__m", read, shared)

#pragma section("ARXCOMMAND$__z", read, shared)

{code}



then &__pArxCmdMapEntryFirst + 1 would point to the first _ARXCOMMAND_ENTRY*
in section ARXCOMMAND$__m

and &__pArxCmdMapEntryLast would be the first address after section
ARXCOMMAND$__m

But the sections are actually defined as:

{code}

#pragma section("ARXCOMMAND$__a", read, shared)

#pragma section("ARXCOMMAND$__z", read, shared)

#pragma section("ARXCOMMAND$__m", read, shared)

{code}



which would make &__pArxCmdMapEntryFirst + 1 point to &__pArxCmdMapEntryLast

and &__pArxCmdMapEntryLast point to the address before the first
_ARXCOMMAND_ENTRY* in section ARXCOMMAND$__m

I'm confused...
3 REPLIES 3
Message 2 of 4
Anonymous
in reply to: Anonymous

Kyle:

The part of the section name following the $ has special meaning, and is
used to order the pseudo-sections within a single section. Knowing this, it
should be clear why the a, m, and z were chosen; however they could just as
well have used f, g, and h. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
Message 3 of 4
Anonymous
in reply to: Anonymous

Owen,

That was one of the first things that I thought about but I couldn't find
any information in the MSDN Library about it.
Is this feature part of something larger than #pragma section? Do you know
what it's called or where it might be explained in a reference?
Thank you for the reply.


"Owen Wengerd" wrote in message
news:6129477@discussion.autodesk.com...
Kyle:

The part of the section name following the $ has special meaning, and is
used to order the pseudo-sections within a single section. Knowing this, it
should be clear why the a, m, and z were chosen; however they could just as
well have used f, g, and h. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
Message 4 of 4
Anonymous
in reply to: Anonymous

Kyle:

This is a feature (possibly undocumented) of the Microsoft linker. I
don't know whether other linkers use the same technique. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>


"Kyle Wakefield" wrote in message
news:6129482@discussion.autodesk.com...
Owen,

That was one of the first things that I thought about but I couldn't find
any information in the MSDN Library about it.
Is this feature part of something larger than #pragma section? Do you know
what it's called or where it might be explained in a reference?
Thank you for the reply.

[...]

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

Post to forums  

Autodesk Design & Make Report

”Boost