Problems using GStack->GetLocalAddressList(LList) in C++

33 Views Asked by At

I am trying to use the GetLocalAddressList() as referenced in https://www.indyproject.org/2014/03/14/tidstack-addlocaladdressestolist-method-is-now-deprecated/

I have translated the Delphi code to C++

#include <IdStack.hpp>

TIdStackLocalAddressList* LList;
TIdStackLocalAddress* LAddr;
int idx;

try {
    LList = new TIdStackLocalAddressList();
    try {
        GStack->GetLocalAddressList(LList);
        for (idx = 0; idx < LList->Count - 1; idx++) {
            LAddr = LList->Addresses[idx];
            switch (LAddr->IPVersion) {
                case Id_IPv4:
                    // Add to list Items
                    ListBox1->Items->Add(LAddr->IPAddress);
                    break;
                case Id_IPv6:
                    break;
                default:;
            }
        }
    } catch (...) {
    }
} __finally
{
    delete LList;
}

I get

Project Project1.exe raised exception class 0xc0000005 with message 'Exception 0xc0000005 encountered at address 0x408b38: Access violation reading location 0x00000000'.

When I execute GStack->GetLocalAddressList(LList);

I assume that it is because I haven't made a GStack object, but I have no reference as to how/when to do that. I have looked on the web an can't seem to find any good references for using Indy with Builder :(

Can someone help out? Thanks is advance.

2

There are 2 best solutions below

1
Remy Lebeau On BEST ANSWER

GStack is a global singleton object that Indy uses to abstract access to platform-specific APIs.

If you have other Indy components alive at the time you run this code, the GStack object is already created for you. But if there are no objects alive, you have to create the GStack object before you can use it.

Fortunately, the singleton is reference-counted - it is created when the 1st reference is added, and then destroyed when the last reference is removed. The TIdStack class has public static methods for managing this reference counting. You should use those methods when using GStack directly, if you are not sure whether other Indy components are alive or not, eg:

TIdStack::IncUsage(); // creates GStack if needed
try
{
    // now you can safely use GStack as needed...
}
__finally
{
    TIdStack::DecUsage();  // destroys GStack if needed
}

On a side note, your for loop should not be subtracting 1 from the LList->Count when using the < comparison. The loop should be:

for (idx = 0; idx < LList->Count; idx++)
0
JKofsky On

Thank you @Remy. Yes this is for stand-alone usage, to load a ComboBox for user selection of a Binding IP. With newer computers having multiple NIC, I needed a way for the user to select which network to use for talking to other applications.

For those looking for how to do this, Below is the modified code:

#include <IdStack.hpp>
// ----------------------------

TIdStackLocalAddressList* LList;
TIdStackLocalAddress* LAddr;
int idx;

try {
    LList = new TIdStackLocalAddressList();
    TIdStack::IncUsage(); // creates GStack if needed
    try {
        GStack->GetLocalAddressList(LList);
        for (idx = 0; idx < LList->Count; idx++) {
            LAddr = LList->Addresses[idx];
            switch (LAddr->IPVersion) {
                case Id_IPv4:
                    // Add to list Items
                    ListBox1->Items->Add(LAddr->IPAddress);
                    break;
                case Id_IPv6:
                    // Right Now I don't care about IPv6
                    break;
                default:;
            }
        }
    } catch (...) {
    }
} __finally
{
    TIdStack::DecUsage(); // destroys GStack if needed
    delete LList;
}
//

My App is using a second NIC for Audio-Over-IP (AOIP) and I didn't want the Apps using the same NIC as the Audio.