0

I have this function that reads memory, and returns a string (or whatever type resides in memory) that's at the specified address. But I'm getting the error:

error: invalid conversion from 'uint64_t to 'const char*'

What am I doing wrong? I've seen it done before in this exact way. Here's code of what I'm trying to do:

template<typename T>
T ReadMemory(uint64_t addr, size_t size)
{
    uint64_t some_address = addr;
    size_t string_size = size;
    uint64_t return_value;
    //store address contents into return_value using driver

    //cast typename on return_value
    return (T)return_value;
}

int main()
{
    string foo = ReadMemory<string>(some_address,some_size);
}
Joe Defill
  • 439
  • 1
  • 4
  • 16
  • 2
    First off, do you maybe mean `std::uintptr_t` instead of `uint64_t`? – aschepler Apr 10 '17 at 23:55
  • Negative, I'm using either ULONG or uint64_t. Either way, same casting problem happens with uintptr_t – Joe Defill Apr 10 '17 at 23:59
  • 4
    Casting to an std::string makes no sense. – Karoly Horvath Apr 11 '17 at 00:01
  • Please don't use C-style type casts in C++. – dtell Apr 11 '17 at 00:06
  • 1
    @JoeDefill: I can pretty much gaurantee you want `std::uintptr_t`, which is `ulong` in 32 bit builds, and `uint64_t` in 64 bit builds. – Mooing Duck Apr 11 '17 at 00:11
  • @JoeDefill : The only way in which what you're (I think) trying to do would be possible is if you did a `reinterpret_cast` to `T*` on the address and dereferenced the casted pointer as the function's return value. This would require an instance of `std::string` (per the example call in `main`) to exist at the specified address. Are you sure that this is what you want to do? The question isn't clear in that regard. – Daniel Kamil Kozar Apr 11 '17 at 00:17
  • `string` is different to `const char *`. Either this isn't your real code, or you're doing something hideous beforehand – M.M Apr 11 '17 at 00:42

2 Answers2

1

Note: Do not cast C style

Since you are using C++ you should avoid casting C style like (type) value. See Why use static_cast(x) instead of (int)x? for a C++ like version.

Now let's solve your problem.

Template specialization

The idea is to specialize a template for each used generic type.

Your header could contain

template<typename T>
T ReadMemory(uint64_t addr, size_t size);

and your implementation containes

/* type is std::string */
template<>
std::string ReadMemory(uint64_t addr, size_t size){
    uint64_t some_address = addr;
    size_t string_size = size;
    uint64_t return_value;
    //store address contents into return_value using driver

    //cast typename on return_value
    return std::to_string(return_value);
}

/* type is uint64_t */
template<>
unit64_t ReadMemory(uint64_t addr, size_t size){
    uint64_t some_address = addr;
    size_t string_size = size;
    uint64_t return_value;
    //store address contents into return_value using driver

    //cast typename on return_value
    return return_value;
}

and so on for all types you want to implement. See How do I explicitly instantiate a template function? for further information.

C++17 solution

C++17 will add an amazing new feature called if constexpr. As soon as this will be supported by compilers you can use it like this:

template<typename T>
T ReadMemory(uint64_t addr, size_t size){
    uint64_t some_address = addr;
    size_t string_size = size;
    uint64_t return_value;
    //store address contents into return_value using driver

    /* type is std::string */
    if constexpr (std::is_same<T,std::string>::value){
        return std::to_string(return_value);
    }
    /* type is uint64_t */
    if constexpr (std::is_same<T,uint64_t>::value){
        return return_value;
    }
}
Community
  • 1
  • 1
dtell
  • 2,488
  • 1
  • 14
  • 29
  • 1
    To avoid code duplication I would suggest having the conversion from `return_value` to the return type be its own function with specializations; if all specializations of ReadMemory would have the same initial code – M.M Apr 11 '17 at 00:44
0

You cannot cast a number to a std::string. Instead, use std::to_string from C++11. Eg, with template specialization:

template<>
std::string ReadMemory(uint64_t addr, size_t size)
{
    uint64_t some_address = addr;
    size_t string_size = size;
    uint64_t return_value;
    //store address contents into return_value using driver

    //cast typename on return_value
    return std::to_string(return_value);
}

template<>
std::wstring ReadMemory(uint64_t addr, size_t size)
{
    uint64_t some_address = addr;
    size_t string_size = size;
    uint64_t return_value;
    //store address contents into return_value using driver

    //cast typename on return_value
    return std::to_wstring(return_value);
}
Daniel Waechter
  • 2,574
  • 2
  • 21
  • 21