How to return different structures in a function with a value defined in Runtime?

Asked

Viewed 58 times

-1

Hello, I am working on a project for Windows that has a structure (of Windows itself) that changes according to the architecture of the system (x86/x64), how to return the correct structure for a function based on the information of which Windows architecture the user is using?

For example:

struct s_arch_x86
{
    uint32_t    callback0;
    uint32_t    flags;
    uint32_t    callback1;
};

struct s_arch_x64
{
    uint64_t    callback0;
    uint32_t    flags;
    uint32_t    flags2;
    uint64_t    callback1;
};

template < typename T1, typename T2 >
auto get_struct_based_on_arch(uint32_t arch, uintptr_t address)
{
    return arch == 32 ? reinterpret_cast<T1>(address) : reinterpret_cast<T2>(address);
}

get_struct_based_on_os_arch<s_arch_x86*, s_arch_x64*>(get_os_arch(), ptr)->callback1 = 0;

In MSVC with C++17 I have the following error when compiling the above code: error C2446: ':': no conversion from 'T2' to 'T1'

  • 1

    Is it for all these versions? (not that you need any, probably in the worst case #ifdef resolves at all)

  • No, any of it

2 answers

0

I could not find the use for this, but you can receive by template the architecture you want to use.

Link to an example: https://godbolt.org/z/MKWTcV.

#include <cstdint>

struct s_arch_x86
{
    uint32_t    callback0;
    uint32_t    flags;
    uint32_t    callback1;
};

struct s_arch_x64
{
    uint64_t    callback0;
    uint32_t    flags;
    uint32_t    flags2;
    uint64_t    callback1;
};

template <typename ARCH>
auto getArchStructure(std::uintptr_t address)
{
    return reinterpret_cast<ARCH*>(address);
}

int main()
{
    auto x32 = getArchStructure<s_arch_x64>(0xFFFFFF);
    auto x64 = getArchStructure<s_arch_x86>(0xFFFFFF);

    x32->callback1 = 0;

    x64->callback1 = 0;

    return 1;
}

0


I think it’s too complicated...

Unless there is some reason to use templates (at least I don’t see any) I would do something like this:

if (get_os_arch() == 32)
{
  s_arch_x86* x86 = (s_arch_x86*)ptr;
  x86->callback1 = 0;
}
else
{
  s_arch_x64* x64 = (s_arch_x64*)ptr;
  x64->callback1 = 0;
}

This is just an illustrative code, I don’t even know if it’s totally correct, but the important thing for me would be nay use that complication of templates...

Encapsulating in a function:

void resetCallback(uintptr_t ptr)
{
  if (get_os_arch() == 32)
  {
    s_arch_x86* x86 = (s_arch_x86*)ptr;
    x86->callback1 = 0;
  }
  else
  {
    s_arch_x64* x64 = (s_arch_x64*)ptr;
    x64->callback1 = 0;
  }
}
  • The problem is that lottery the if/Else conditional and block code

  • so it’s just encapsulating in a function...

  • It is not so simple, this structure changes according to the architecture, version and build of Windows, it is a structure related to windows driver, there are several different builds in windows 10(10240, 10586, 14393, 15063, 16299, 17134, 17763, 18362, 18363), lottery the if/Else if code or switch anyway, I believe it does not have a better way

  • as I said above, it is only encapsulate in a function to avoid repetition of if/switch

Browser other questions tagged

You are not signed in. Login or sign up in order to post.