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

how to access static variable in DBX

11 REPLIES 11
Reply
Message 1 of 12
nk_klein
607 Views, 11 Replies

how to access static variable in DBX

using the ARX wizard, Create DBX project and then add Custom Object(Just follow the "Setp 6-Custom Entities" in ObjectArx Tutorial).

the auto generated code:
///////
....
class DLLIMPEXP AsdkEmployee : public AcDbEllipse {

public:
ACRX_DECLARE_MEMBERS(AsdkEmployee) ;

protected:
static Adesk::UInt32 kCurrentVersionNumber ;
.....
////////
here i take the static variable kCurrentVersionNumber for example, if i want to obtain the value, I add a function getVersion() to return the value:
//////
static Adesk::UInt32 getVersion()
{
return kCurrentVersionNumber;
}
/////
Now, in another ARX project, I want to use the AsdkEmployee class in that DBX. first include the header file, add the lib dependency, invoke the static function:
///
int ver = AsdkEmployee::getVersion();
...
///
link error:

1>acrxEntryPoint.obj : error LNK2001: unresolved external symbol "protected: static unsigned long AsdkEmployee::kCurrentVersionNumber" (?kCurrentVersionNumber@AsdkEmployee@@1KA)

if i modify
#define DLLIMPEXP
into
#define DLLIMPEXP __declspec(dllimport)
build success

But see the comments:

#ifdef EMPLOYEE_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
//----- Note: we don't use __declspec(dllimport) here, because of the
//----- "local vtable" problem with msvc. If you use __declspec(dllimport),
//----- then, when a client dll does a new on the class, the object's
//----- vtable pointer points to a vtable allocated in that client
//----- dll. If the client dll then passes the object to another dll,
//----- and the client dll is then unloaded, the vtable becomes invalid
//----- and any virtual calls on the object will access invalid memory.
//-----
//----- By not using __declspec(dllimport), we guarantee that the
//----- vtable is allocated in the server dll during the ctor and the
//----- client dll does not overwrite the vtable pointer after calling
//----- the ctor. And, since we expect the server dll to remain in
//----- memory indefinitely, there is no problem with vtables unexpectedly
//----- going away.
#define DLLIMPEXP
#endif


Is there any mistake in the above steps? if i want to access STATIC variable from ARX project, what should i do?
11 REPLIES 11
Message 2 of 12
Anonymous
in reply to: nk_klein

Rather than export the entire class, just export separate global functions
as needed:

__declspec(dllexport) Adesk::UInt32 GetAdskEmployeeVersion()
{
return AdskEmployee::kCurrentVersionNumber;
}

__declspec(dllexport) Adesk::UInt32 GetAdskEmployeeMember( AdskEmployee*
pEmployee )
{
return pEmployee->GetMember();
}

then in the client:

__declspec(dllimport) Adesk::UInt32 GetAdskEmployeeVersion();
__declspec(dllimport) Adesk::UInt32 GetAdskEmployeeMember( AdskEmployee*
pEmployee );
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
Message 3 of 12
nk_klein
in reply to: nk_klein

Thanks, Owen!

That means I have to supply extra gloal functions in order to export static memeber variable, right?

In this example, if I want to create AsdkEmployee object and access static variable in the client side, I have to export the entire class first, and then export the global function.
like this:

//////////AsdkEmployee.h///////////////

#ifdef EMPLOYEE_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP // empty
#endif

class DLLIMPEXP AsdkEmployee : public AcDbEllipse
{
....
protected:
static Adesk::UInt32 kCurrentVersionNumber ;
public:
static Adesk::UInt32 getVersion()
{
return AsdkEmployee::kCurrentVersionNumber;
}
......
}

// global function

DLLIMPEXP Adesk::UInt32 GetAdskEmployeeVersion()
{
return AdskEmployee::getVersion();
}
////////////////////// Message was edited by: nk_klein
Message 4 of 12
Anonymous
in reply to: nk_klein

You should *not* export the entire class. Just export separate functions
as needed. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
Message 5 of 12
nk_klein
in reply to: nk_klein

thx!

But if I want to instantiate the AsdkEmployee class in the client, I need to export the class.
Message 6 of 12
Anonymous
in reply to: nk_klein

> But if I want to instantiate the AsdkEmployee class in the client,
> I need to export the class.

No you don't. Just export a function that creates an instance of the
class and returns a pointer to the new instance. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
Message 7 of 12
nk_klein
in reply to: nk_klein

I got it!
:)
Message 8 of 12
nk_klein
in reply to: nk_klein

😞
Maybe I'm wrong, but I have another question.
If only export function and return a pointer, how can the client know the class type?
Here, client don't know the existance of AsdkEmployee class type.
Message 9 of 12
Anonymous
in reply to: nk_klein

> If only export function and return a pointer, how can the client
> know the class type?

The client has to include the class header file (with DLLIMPEXP defined
for importing instead of exporting). 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
Message 10 of 12
nk_klein
in reply to: nk_klein

I'm confused again. how can import class from the DLL which doesn't export that class?
please see the attachment. In the Caller project, how to deal with Callee object if ignore the __declspec(dllimport) in Callee.h.
how to access static variable s_nCount and member function testFun() simultaneously in the Caller?
Message 11 of 12
Anonymous
in reply to: nk_klein

> I'm confused again. how can import class from the DLL
> which doesn't export that class?

You should *not* import (or export) the class. Remove the 'CALLEE_API'
from the class declaration in Callee.h, then change your macro definitions
to:
#ifdef CALLEE_EXPORTS
#define CALLEE_API __declspec(dllexport)
#else
#define CALLEE_API __declspec(dllimport)
#endif

Once this is done, you can define fnCallee in Calle.cpp like this:
int fnCallee(void)
{
return CCallee::s_nCount;
}

In Caller.cpp, you cannot construct a CCallee object on the stack. If you
could, CCallee's vtable would reside in Caller's address space. That is the
problem that arises when you export the class, and it's the reason you
should not export the class. Instead, call an exported function that
returns a new CCallee that is constructed in CCallee's module. Declare this
function in CCallee.h:

CALLEE_API CCallee* ConstructCallee(void);

Define the function in Callee.cpp:

CCallee* ConstructCallee(void)
{
return new CCallee;
}

In Caller.cpp, call that function:
CCallee* pNewCallee = ConstructCallee();

Now you have a new CCallee, and it was constructed with its vtable in the
CCallee module's address space. If you need to call CCallee member
functions from CCaller, then you should either make those member functions
virtual; or export a non-member helper function from the CCallee module that
accepts a CCallee* argument, calls its member function, then returns the
result.

I hope this helps. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
Message 12 of 12
nk_klein
in reply to: nk_klein

Owen,
you're so kind! I understand
Thank you very very much!
:-)

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

Post to forums  

Autodesk Design & Make Report

”Boost