Some socket gurus might know a direct way to set it. But it's easier to just query the system for it.  This will correctly set both "flowinfo" and "scope_id" for you.
General approach is this:
Invoke getifaddrs to get a list of ifaddrs instances.
Enumerate the list of ifaddrs returned from this api until you find the AF_INET6 adapter with the IFF_LOOPBACK bit set on the ifa_flags member.  This is the adapter you want to bind to.
Now that you have a pointer to the ifaddrs instance, cast its ifa_addr member to a (sockaddr_in6*).  Copy this structure into your own addr and set the port.
Some sample code below:
struct sockaddr_in6 addr = {0};
ifaddrs* pList = NULL;
ifaddrs* pAdapterFound = NULL;
ifaddrs* pAdapter = NULL;
getifaddrs(&pList);
pAdapter = pList;
while (pAdapter)
{
    if ((pAdapter->ifa_addr != NULL) && 
        (family == pAdapter->ifa_addr->sa_family == AF_INET6) &&
        (pAdapter->ifa_flags & IFF_LOOPBACK))
    {
        pAdapterFound = pAdapter;
        break;
    }
    pAdapter = pAdapter->ifa_next;
}
if (pAdapterFound)
{    
    // C++ way to copy the sockaddr_in6 struct
    addr = *(reinterpret_cast<sockaddr_in6*>(pAdapterFound->ifa_addr));  // C++
    // If you are coding in C instead of C++
    // memcpy(&addr, pAdapterFound->ifa_addr, sizeof(addr));
    addr.sin6_port = htons(0); // or whatever port you want to bind to
}
freeifaddrs(pList);
You are welcome to reference a helper function I have called GetSocketAddressForAdapter.  You could invoke it as follows:
GetSocketAddressforAdapter(AF_INET6, "::1", 0, &address);