Passing array into function via void Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
awsdert
Super wx Problem Solver
Super wx Problem Solver
Posts: 324
Joined: Fri Aug 26, 2011 5:04 pm

Passing array into function via void

Post by awsdert »

Google is useless when you're looking for something like this. Anyway I'm trying to make it easier to find errors in my Dump and Find code by simply setting up the buffers then passing them to functions that will handle the rest (instead of using preprocessor definitions to shorten code). I can't seem to get it right so I'm now asking the experts to explain how it's done. This is what I have so far.

Code: Select all

void ME::Dump8( void )
{
	//const wxChar* resultText = wxT( "Results: %i" );
	u32 valSize = 1;
	HANDLE appHandle = GAP();
	// RAM
	DWORD ramAddress = GARS( 0 );
	u64 ramSize = GARM( 0 );
	u8* ramBuff = HCReadM8( appHandle, ramAddress, ramSize );
	Dump( appHandle, valSize, ramBuff );
/// skipped code
void ME::Dump( HANDLE appHandle, u32 valueSize, void* ramBuff )
{
	const wxChar* resultText = wxT("Results: %i");
	u64 ramSize = GARM(0);
	u64 i = 0;
	u64 resultNo = 0;
Muetdhiver
Super wx Problem Solver
Super wx Problem Solver
Posts: 323
Joined: Sun Jun 08, 2008 11:59 am
Location: Bordeaux, France

Re: Passing array into function via void

Post by Muetdhiver »

Hi, I can't figure out what you want.... Can you explain more ???

Moreover, it is no wxWidgets related but it is a simple C question....

Your function void ME::Dump( HANDLE appHandle, u32 valueSize, void* ramBuff )
is not ended, and you never read ramBuff. What you want to achieve ?

If you want to read it, just cast the pointer to a u8 pointer....

Code: Select all

u8* myu8ramBuff = reinterprete_cast<u8*>( ramBuff );
Why not passing directly a u8* to the function ?
OS: Ubuntu 11.10
Compiler: g++ 4.6.1 (Eclipse CDT Indigo)
wxWidgets: 2.9.3
awsdert
Super wx Problem Solver
Super wx Problem Solver
Posts: 324
Joined: Fri Aug 26, 2011 5:04 pm

Re: Passing array into function via void

Post by awsdert »

Dump(etc) is ended I just gave you the snippets that matter in this case because the code being used works when used via preprocessor definitions but that adds to size and difficulty in debugging when refining. I stuck the question here because I get faster responses and it does say "C++ Development".
What I want is basically to pass buffers of varying types to be dealt with by one function e.g.

Code: Select all

u8* buff8[u8len]
u16* buff16[u16len]
u32* buff32[u32len]
u64* buff64[u64len]
Dump(u8len, buff8)
Dump(u16len, buff16)
Dump(u32len, buff32)
Dump(u64len, buff64)
Overloading would just mean repeating code which I would like to avoid if possible, I know that when used right void can take any variable type but I do not know how to do that with buffers.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Passing array into function via void

Post by PB »

Muetdhiver's solution will work. Another approach would be to templatize the function. But unless the allocated array has always the same item count, you still need to pass the size of the allocated block (or rather the item count). If I understand your code correctly, that u*size is just a size of an element, right?
awsdert
Super wx Problem Solver
Super wx Problem Solver
Posts: 324
Joined: Fri Aug 26, 2011 5:04 pm

Re: Passing array into function via void

Post by awsdert »

But wouldn't that solution be creating a new buffer? These buffers can be rather large, as for item count that is calculated based on valueSize before the function loops through. Basically my tool reads from another processes memory based on a member address and size specified by user, if I could I would just use a union because I don't need to worry about undefined behaviour then and can just use a switch statement to capture the relevant value before continuing to the test code of the loop, whenever I try that though I end up being told by the compiler that I'm not using it right but it doesn't actually tell me what I'm doing wrong either.

Edit: Jut thought you might want to see how I was trying to use the union so here it is:

Code: Select all

union RAMB
{
    u8* u8Value;
    u16* u16Value;
    u32* u32Value;
    u64* u64Value;
}
RAMB ramBuff;
ramBuff.u8Value = HCRead8M(appHandle, ramAddress, ramSize);
I had the union declared before my Dump8 function and then tried creating the buffer as normal like above.
Last edited by awsdert on Fri Mar 02, 2012 2:36 pm, edited 1 time in total.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Passing array into function via void

Post by PB »

awsdert wrote:But wouldn't that solution be creating a new buffer?
No.

And as you have just said, this is C++ forum, your solution is pure C. In C++ you shouldn't use raw pointers unless you really have to, and you should never use C arrays but STL containers instead. Anyway, the templatized simplified solution with example would look like this:

Code: Select all

template <class T>
void FillValues(T* data, size_t size) 
{
    for (size_t i = 0; i < size; i++)
        data[i] = i;        
}


template <class T>
int FindValue(T value, T* data, size_t size) 
{
    for (size_t i = 0; i < size; i++) {
        if (data[i] == value)
            return i;
    }
    return -1;
}

void Search()
{        
    size_t numElements = 100;
    try {        
        int result;
                
        wxUint8 u8value = 8;
        wxUint8* u8ptr = new wxUint8[numElements];
    
        FillValues(u8ptr, numElements);
        result = FindValue(u8value, u8ptr, numElements);
       delete[] u8ptr;
    
        wxUint64 u64value = 64;
        wxUint64* u64ptr = new wxUint64[numElements];
        
        FillValues(u64ptr, numElements);
        result = FindValue(u64value, u64ptr, numElements);        
       delete[] u64ptr;
    }
    catch (std::bad_alloc&) {
        // handle out of memory error here
    }
}
It is still an ugly hybrid of C and C++ (using containers and algorithms would be a preferred solution), but I think it's enough as an example. And no, no copying buffers is being done here. Neither would be if you used e.g. vector or valarray, assuming you pass the variable by (const) reference and not by value.
Last edited by PB on Fri Mar 02, 2012 2:40 pm, edited 1 time in total.
awsdert
Super wx Problem Solver
Super wx Problem Solver
Posts: 324
Joined: Fri Aug 26, 2011 5:04 pm

Re: Passing array into function via void

Post by awsdert »

I forgot about template, I'll give that a try instead. Thanks.

Edit: Compiler now complains that my functions prototype does not match any in the class yet the candidate is exactly the same, what am I doing wrong?

Code: Select all

template <class T>

void ME::Dump8( void )
{
	const wxChar* resultText = wxT( "Results: %i" );
	u32 valSize = 1;
	HANDLE appHandle = GAP();
	// RAM
	DWORD ramAddress = GARS( 0 );
	u64 ramSize = GARM( 0 );
	T<u8> *ramBuff = HCReadM8( appHandle, ramAddress, ramSize );
Muetdhiver
Super wx Problem Solver
Super wx Problem Solver
Posts: 323
Joined: Sun Jun 08, 2008 11:59 am
Location: Bordeaux, France

Re: Passing array into function via void

Post by Muetdhiver »

Actually, you are wrong about what you want to do and the way used to set up the solution. [-X

Using void pointers in interfaces implies that you know what to do in interface implementation. I mean, this is not because you use void* in your function definition that this function will be generic and then able to use any kind of buffer types.

If you call the interface Dump by passing a buffer of type u8*, you always have to know in the Dump function that you are using a u8* (so, cast the void pointer).

To do something else, that is to say to have a generic function, you have many other choices, have a look at them :

- I'm not fond of them, but as said PB, C++ templates correspond to your problem,
- Another paradigm is to use inheritance to have a generic mother class.
- Another is to use the minimal sized type (in your example u8) and consider other buffers as a multiple of standard buffer, I mean :

size of buffer of u8 = (size of buffer of u16 / 2) = (size of buffer of u32 / 4) etc.....
OS: Ubuntu 11.10
Compiler: g++ 4.6.1 (Eclipse CDT Indigo)
wxWidgets: 2.9.3
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Passing array into function via void

Post by PB »

Here is a simple example of C++ solution. Warning: the code was not tested, I might explode right into your face. It searches only for a single value, to adjust it to search for a sequence is left as an exercise. ;)

Code: Select all

template <class T>
bool MyReadProcessMemory(HANDLE hProcess, LPCVOID baseAddress, size_t bytesToRead, std::vector<T>& data)
{
    try {        
        wxCHECK(bytesToRead >= sizeof(T) && bytesToRead % sizeof(T) == 0, false);

        data.resize(bytesToRead / sizeof(T));

        SIZE_T bytesRead;

        if (!ReadProcessMemory(hProcess, baseAddress, 
                reinterpret_cast<LPVOID>(&data.front()), 
                bytesToRead, &bytesRead) 
            || bytesToRead != bytesRead) {
        
            data.clear();
            return false;        
        }
        return true;                        
    }
    catch (std::bad_alloc&) {
        // handle out of memory error here
    }
    return false;
}

template <class T>
int FindValue(HANDLE hProcess, LPCVOID baseAddress, size_t bytesToRead, T value)
{
    std::vector<T> data;

    if (MyReadProcessMemory(hProcess, baseAddress, bytesToRead, data)) {
         
        std::vector<T>::iterator it;

        it = std::find(data.begin(), data.end(), value);
        if (it != data.end()) {
            return it - data.begin();
        }
    }
    return -1;
}
Now you can do

Code: Select all

wxUint8 u8value = 8;    
int result = FindValue(hProcess, baseAddress, bytesToRead, u8value);
just like like you can do

Code: Select all

wxUint64 u64value = 64;
int result = FindValue(hProcess, baseAddress, bytesToRead, u64value);
But if you need to search the same block of memory several times using different T type, you have to chose another approach. I don't know what you will use the code for. Also notice the value returned from FindValue is not an address in bytes, but index of an element, changing this would be very simple though.
In the end this code might be useless to you as it is, but it may serve as an example of C++ solution.
awsdert
Super wx Problem Solver
Super wx Problem Solver
Posts: 324
Joined: Fri Aug 26, 2011 5:04 pm

Re: Passing array into function via void

Post by awsdert »

Thanks but it won't help on this occasion. My app reads large blocks at a time and then loops through providing a number of results equivalent to the pieces of memory that matched the search criteria (which can be multiple things at once), oh well I'll just revert back to multi-function old code that worked.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Passing array into function via void

Post by PB »

What about this? I think this should be useful. You can now use the same memory block using different types.

Code: Select all

template <class T>
struct MyMemoryData {
    typedef T value_type;
    
    value_type* data;
    size_t size;

    MyMemoryData() { data = NULL, size = 0;  }
    MyMemoryData(void* ptr, size_t ptrSize) { *this = VoidPtr2MyMemory<T>(ptr, ptrSize); }
    T operator[](size_t n) const { wxASSERT(data && n < size); return data[n]; }    
};

template <class T>
MyMemoryData<T> VoidPtr2MyMemory(void* ptr, size_t ptrSize)
{  
    wxASSERT(ptr);
    wxASSERT(ptrSize >= sizeof(T) && ptrSize % sizeof(T) == 0);

    MyMemoryData<T> mm;

    mm.data = reinterpret_cast<T*>(ptr);
    mm.size = ptrSize / sizeof(T);

    return mm;
}

void TestMemoryData()
{
     try {        
        const size_t size = 4096;
        wxByte* ptr = new wxByte[size]; // using a smart ptr would be a good idea here

       MyMemoryData<wxUint8> mm8(ptr, size); 
        MyMemoryData<wxUint16> mm16(ptr, size); 
        MyMemoryData<wxUint32> mm32(ptr, size); 
        MyMemoryData<wxUint64> mm64(ptr, size);

        wxLogDebug(wxString::Format("mm8: type = %s, size=%d, element size = %d", 
            typeid(mm8[0]).name(), mm8.size, sizeof(mm8[0])));        
        wxLogDebug(wxString::Format("mm16: type = %s, size=%d, element size = %d", 
            typeid(mm16[0]).name(), mm16.size, sizeof(mm16[0])));        
        wxLogDebug(wxString::Format("mm32: type = %s, size=%d, element size = %d", 
            typeid(mm32[0]).name(), mm32.size, sizeof(mm32[0])));        
        wxLogDebug(wxString::Format("mm64: type = %s, size=%d, element size = %d", 
            typeid(mm64[0]).name(), mm64.size, sizeof(mm64[0])));        

        /* prints
        mm8: type = unsigned char, size=4096, element size = 1
        mm16: type = unsigned short, size=2048, element size = 2
        mm32: type = unsigned int, size=1024, element size = 4
        mm64: type = unsigned __int64, size=512, element size = 8
        */

        delete[] ptr;
     } catch (std::bad_alloc&) {
        // handle out of memory error here
    }
    
}
Last edited by PB on Fri Mar 02, 2012 4:49 pm, edited 5 times in total.
awsdert
Super wx Problem Solver
Super wx Problem Solver
Posts: 324
Joined: Fri Aug 26, 2011 5:04 pm

Re: Passing array into function via void

Post by awsdert »

Figured out how to do it, just had to use void** as the parameter and then use (void**)ramBuff when calling it, just got some debugging to do then my function should be good to go.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Passing array into function via void

Post by PB »

OK then, so much for C++ and bugfree readable code. I still believe you should rethink your general approach to coding though. :(

BTW, I wonder if you have ever accepted someone else's solution. I remember you refusing perfect proven and very fast solution of converting hexadecimal string to a number and using an extremely inefficient solution of yours instead. You should really try to listen to others (and no, by others, I don't mean me), at least sometimes. You can save yourself a lot of time and effort and maybe even learn something. :wink:
awsdert
Super wx Problem Solver
Super wx Problem Solver
Posts: 324
Joined: Fri Aug 26, 2011 5:04 pm

Re: Passing array into function via void

Post by awsdert »

Thanks, I haven't refused that hexadecimal one, I just haven't gotten round to trying yet because I'm focusing on code that needs looking over first, speed is my second priority however once I finish implementing everything I will try out that code of yours (I have all the forum topics that I started bookmarked). The goal is for everything to just plug into each other without error.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Passing array into function via void

Post by PB »

OK. Also my previous solution wouldn't be of any use if you need to search for a value in a random memory block, where the value could be spread across the borders of value sized elements.

Maybe something simple like this would suffice

Code: Select all

template <class T>
void* FindValue(void* ptr, size_t size, T value)
{
    wxCHECK(ptr, NULL);
    wxCHECK(size >= sizeof(T) && size % sizeof(T) == 0, NULL);
   
    wxByte* bytes = reinterpret_cast<wxByte*>(ptr);
    wxByte* maxAddress = bytes + size - sizeof(value);

    while (bytes <= maxAddress) {
        T v = *reinterpret_cast<T*>(bytes);
        if (v == value)
            return bytes;
        bytes++;
    }
    return NULL;
}

void TestFindValue()
{
    const size_t size = 256;
    wxByte* ptr = new wxByte[size];
   
    void* result;
   
    // test for 8-bit int
    for (int i = 0; i < size; i++)
        ptr[i] = i;

    wxUint8 u8 = 42, found8;    
    result = FindValue(ptr, size, u8);
    if (result) {
        found8 = *(reinterpret_cast<wxUint8*>(result));
        wxASSERT(u8 == found8);
        wxASSERT(reinterpret_cast<wxUint8*>(result)-ptr == u8);
    }

    // and now test for 64-bit value
    memset(ptr, 0, size);    
    wxUint64 u64 = wxUint64(UINT_MAX) + 42, found64;    
    size_t offset = 5;
    // following ugly line sets value at offset of 5 bytes to u64 so we can find it later
    *reinterpret_cast<wxUint64*>(ptr+offset) = u64;
    result = FindValue(ptr, size, u64);
    if (result) {
        found64 = *(reinterpret_cast<wxUint64*>(result));
        wxASSERT(u64 == found64);
        wxASSERT(reinterpret_cast<wxUint8*>(result)-ptr == offset);
    }

    delete[] ptr;
}
}
But if you need to search the same memory block using differently sized variables often, it would be much more efficient to do that in a single loop (taking care of not reading beyond the pointer memory) instead of calling FindValue() repeatedly. But if you need maximal performance, in the end you will probably have to resort to raw memory compares.

Edit: Oops, I realized that the original code was wrong. Fixed, just to be safe.
Last edited by PB on Fri Mar 02, 2012 9:42 pm, edited 2 times in total.
Post Reply