cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

The 2025 Technology Preview Program is now live. Join today!

Archicad C++ API
About Archicad add-on development using the C++ API.

Changing the Library folder in ARCHICAD12

Not applicable
Hi,

I want to change my project Libraries Folder in ArchiCAD 12.
I am using following function.

Void setupLibrariesForAC12()
{
API_LibrariesInfo libInfo;

memset(&libInfo, 0, sizeof(API_LibrariesInfo));
libInfo.nLib = 2;
libInfo.locations = (IO::Location**) BMAllocateHandle (libInfo.nLib * sizeof(IO::Location, ALLOCATE_CLEAR, 0);
libInfo.useSatellite = false;

new (*libInfo.locations) IO::Location (“C:\\Archicad12\\Archicad Library”);
new (*libInfo.locations + 1) IO::Location (“C:\\Archicad Development Library”);

ACAPI_Environment(APIEnv_SetLibrariesID, &libInfo, NULL);
(*libInfo.locations).~Location();
(*libInfo.locations + 1).~Location();

BMKillHandle(reinterpret_cast<GSHandle *> (&libInfo.locations));
}

But I am getting following errors
err LNK2001:unresolved external symbol “public: virtual class GS::ClassInfo * __thiscall GS::Object::GetClassInfoA(void)const “(?getClassInfoA@object@GS@@UBEPAVClassInfo@2@XZ)
fatal error LNK1120: 1 unresolved externals.

Please help me to solve these errors.
23 REPLIES 23
Ranga wrote:
I want to change my project Libraries Folder in ArchiCAD 12.
I am using following function.
Void setupLibrariesForAC12()
...etc...
Please help me to solve these errors.
Does the problem go away if you write it like this (i.e. changing just part of your function)?

libInfo.locations = (IO::Location**) BMAllocateHandle (libInfo.nLib * sizeof(IO::Location, ALLOCATE_CLEAR, 0); 
libInfo.useSatellite = false; 

(*libInfo.locations)[0] = IO::Location(“C:\\Archicad12\\Archicad Library”);
(*libInfo.locations)[1] = IO::Location(“C:\\Archicad Development Library”);

ACAPI_Environment(APIEnv_SetLibrariesID, &libInfo, NULL); 

BMKillHandle(reinterpret_cast<GSHandle *> (&libInfo.locations)); 		
Ralph Wessel BArch
Central Innovation
Oleg
Expert
Hi,

Have you GSRootImp.LIB in your project ?
Not applicable
Oleg wrote:
Hi,

Have you GSRootImp.LIB in your project ?
Oleg,

What a good surprise to read you. It's a long time. I hope you are fine.
Your GDL and API programmer expertise is missing.

Kliment recently pointed out your "rxDuplicator" Add-On (AC8 & 9), among other jewels.
Years after, the similar tool on AC12, is a bit poor, in comparison.

May we expect from you a come back on AC-Talk?

Cheers,
Olivier
Not applicable
Hi Ralph Wessel,

It is working fine if i use
(*libInfo.locations)[0] = IO::Location("C:\\ArchiCAD 12\\ Archicad Library 12");

but in the run time it is failing
at line
(*libInfo.locations)[0].~Location();

i can't use the try and catch because it is saying "error C2712: Cannot use __try in functions that require object unwinding"

i don't know what to do. can you please help me ranga
Oleg
Expert
Olivier wrote:

What a good surprise to read you. It's a long time. I hope you are fine.

Olivier
Hi Olivier and all, thanks for warm words. I am fine.
I occasionally read the Talk, but I have no time to participate absolutely.
( Also has almost forgotten English language in addition. )
Good luck. I should disappear again.

PS: Ranga, I am sorry for personal messages in your thread.

Oleg
Oleg
Expert
Hi Ranga,

(I am sorry my English)

I am not sure in following, just guessing.

Actually, it seems is a right way:
new (*libInfo.locations) IO::Location ("C:\\Archicad12\\Archicad Library");
new (*libInfo.locations + 1) IO::Location ("C:\\Archicad Development Library");

and then

(*libInfo.locations)->~Location();
(*libInfo.locations + 1)->~Location();

But looking at Location header (Location class), there is :
#if defined (DEBUVERS)
Int32* leakDetector;
#endif

So, sizeof of Location class is different in Debug and Release build.
And I think none of attemts will not work in Debug mode.

Try your code in Release mode. It may works.
I think only GS may explain this.
May be there is a way #undef DEBUVERS in your cpp source before #includes, but not sure.

Oleg
Ranga wrote:
Hi Ralph Wessel,

It is working fine if i use
(*libInfo.locations)[0] = IO::Location("C:\\ArchiCAD 12\\ Archicad Library 12");

but in the run time it is failing
at line
(*libInfo.locations)[0].~Location();
That line is directly calling the object's destructor. In the GS example, this is used because they have used placement new in order to directly call the object's constructor and specify where the object is to be allocated. If you take out the placement new (which was my suggestion) you no longer need to call the destructor - it will fail if you do (which is what you are seeing). Either use the code exactly as I stated or use the GS example, but don't mix them.

I would like someone from GS to comment on this, because I don't see an obvious reason for using placement new to allocate the object. Anyone?
Ralph Wessel BArch
Central Innovation
Oleg
Expert
Hi Ralph,

I agree, GS should comment all of this.

My idea about destructor.

I think it is correct:

(*libInfo.locations)[0] = IO::Location("C:\\ArchiCAD 12\\ Archicad Library 12");

I guess, placement new used only to avoid copy. Just to optimize.
But I think, destructor needs anyway to avoid memory leak at kill handle.
(*libInfo.locations)[0].~Location();

And It is possible that will work for first member of array.
But I think if DEBUVERS is defined then next items of array like
(*libInfo.locations)[1] = IO::Location("C:\\ArchiCAD 12\\ Archicad Library 12");
will not work as copied at wrong place. But really it is correct, you are right.

Intresting stuff. But have no time to test.

Oleg
Oleg wrote:
I guess, placement new used only to avoid copy. Just to optimize.
But I think, destructor needs anyway to avoid memory leak at kill handle.
(*libInfo.locations)[0].~Location();
The destructor call is only necessary if you have allocated the object with placement new. No memory will be leaked because it is has been allocated (and released) as a handle.

There seems no reason to use placement new for allocation in this case. Yes, it is an 'optimisation', but completely pointless because this call would never be used in a context where optimal performance could make an appreciable difference.

Optimising where there is no benefit, especially where is the code becomes less readable or balancing calls like 'new' and 'delete' are necessary, is both wasteful and risky. I would like to know if there is some other reason why the GS example does this.
Ralph Wessel BArch
Central Innovation

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!